mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Update to Chromium revision 304f01a1 (#358063)
- Improve ordering of CefLoadHandler callbacks. OnLoadingStateChange will be called before and after all calls to OnLoadStart and OnLoadEnd. OnLoadStart/OnLoadEnd calls will occur as matching pairs (see http://crbug.com/539952#c2). - Remove the |requesting_url| argument to CefGeolocationHandler:: OnCancelGeolocationPermission. Clients can use the |request_id| argument to track this information themselves. - Fix a crash when loading the PDF extension in multiple browsers with a custom CefRequestContext (issue #1757).
This commit is contained in:
268
libcef/browser/permissions/permission_context.cc
Normal file
268
libcef/browser/permissions/permission_context.cc
Normal file
@@ -0,0 +1,268 @@
|
||||
// Copyright 2015 The Chromium Embedded Framework 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 "libcef/browser/permissions/permission_context.h"
|
||||
|
||||
#include "include/cef_client.h"
|
||||
#include "include/cef_geolocation_handler.h"
|
||||
#include "libcef/browser/browser_context.h"
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/permissions/permission_util.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
#include "content/public/browser/geolocation_provider.h"
|
||||
#include "content/public/browser/permission_type.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/common/origin_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Whether the permission should be restricted to secure origins.
|
||||
bool IsRestrictedToSecureOrigins(content::PermissionType permission) {
|
||||
return false;
|
||||
}
|
||||
|
||||
class CefGeolocationCallbackImpl : public CefGeolocationCallback {
|
||||
public:
|
||||
typedef CefPermissionContext::PermissionDecidedCallback CallbackType;
|
||||
|
||||
explicit CefGeolocationCallbackImpl(const CallbackType& callback)
|
||||
: callback_(callback) {}
|
||||
|
||||
void Continue(bool allow) override {
|
||||
if (CEF_CURRENTLY_ON_UIT()) {
|
||||
if (!callback_.is_null()) {
|
||||
if (allow) {
|
||||
content::GeolocationProvider::GetInstance()->
|
||||
UserDidOptIntoLocationServices();
|
||||
}
|
||||
|
||||
callback_.Run(allow ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK);
|
||||
callback_.Reset();
|
||||
}
|
||||
} else {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefGeolocationCallbackImpl::Continue, this, allow));
|
||||
}
|
||||
}
|
||||
|
||||
void Disconnect() {
|
||||
callback_.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
CallbackType callback_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CefGeolocationCallbackImpl);
|
||||
DISALLOW_COPY_AND_ASSIGN(CefGeolocationCallbackImpl);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
CefPermissionContext::CefPermissionContext(CefBrowserContext* profile)
|
||||
: profile_(profile),
|
||||
weak_ptr_factory_(this) {
|
||||
}
|
||||
|
||||
bool CefPermissionContext::SupportsPermission(
|
||||
content::PermissionType permission) {
|
||||
// Only Geolocation permissions are currently supported.
|
||||
return permission == content::PermissionType::GEOLOCATION;
|
||||
}
|
||||
|
||||
void CefPermissionContext::RequestPermission(
|
||||
content::PermissionType permission,
|
||||
content::WebContents* web_contents,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_frame,
|
||||
bool user_gesture,
|
||||
const BrowserPermissionCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
DecidePermission(permission,
|
||||
web_contents,
|
||||
id,
|
||||
requesting_frame.GetOrigin(),
|
||||
web_contents->GetLastCommittedURL().GetOrigin(),
|
||||
user_gesture,
|
||||
callback);
|
||||
}
|
||||
|
||||
void CefPermissionContext::CancelPermissionRequest(
|
||||
content::PermissionType permission,
|
||||
content::WebContents* web_contents,
|
||||
const PermissionRequestID& id) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
DCHECK(permission == content::PermissionType::GEOLOCATION);
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser =
|
||||
CefBrowserHostImpl::GetBrowserForContents(web_contents);
|
||||
if (browser.get()) {
|
||||
CefRefPtr<CefClient> client = browser->GetClient();
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefGeolocationHandler> handler =
|
||||
client->GetGeolocationHandler();
|
||||
if (handler.get())
|
||||
handler->OnCancelGeolocationPermission(browser.get(), id.request_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CefPermissionContext::ResetPermission(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
profile_->GetHostContentSettingsMap()->SetContentSetting(
|
||||
ContentSettingsPattern::FromURLNoWildcard(requesting_origin),
|
||||
ContentSettingsPattern::FromURLNoWildcard(embedding_origin),
|
||||
permission_util::PermissionTypeToContentSetting(permission),
|
||||
std::string(),
|
||||
CONTENT_SETTING_DEFAULT);
|
||||
}
|
||||
|
||||
ContentSetting CefPermissionContext::GetPermissionStatus(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) const {
|
||||
if (IsRestrictedToSecureOrigins(permission) &&
|
||||
!content::IsOriginSecure(requesting_origin)) {
|
||||
return CONTENT_SETTING_BLOCK;
|
||||
}
|
||||
|
||||
return profile_->GetHostContentSettingsMap()->GetContentSetting(
|
||||
requesting_origin,
|
||||
embedding_origin,
|
||||
permission_util::PermissionTypeToContentSetting(permission),
|
||||
std::string());
|
||||
}
|
||||
|
||||
void CefPermissionContext::DecidePermission(
|
||||
content::PermissionType permission,
|
||||
content::WebContents* web_contents,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
bool user_gesture,
|
||||
const BrowserPermissionCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
if (!requesting_origin.is_valid() || !embedding_origin.is_valid()) {
|
||||
NotifyPermissionSet(permission, id, requesting_origin, embedding_origin,
|
||||
callback, false /* persist */, CONTENT_SETTING_BLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsRestrictedToSecureOrigins(permission) &&
|
||||
!content::IsOriginSecure(requesting_origin)) {
|
||||
NotifyPermissionSet(permission, id, requesting_origin, embedding_origin,
|
||||
callback, false /* persist */, CONTENT_SETTING_BLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
ContentSetting content_setting =
|
||||
profile_->GetHostContentSettingsMap()->
|
||||
GetContentSettingAndMaybeUpdateLastUsage(
|
||||
requesting_origin,
|
||||
embedding_origin,
|
||||
permission_util::PermissionTypeToContentSetting(permission),
|
||||
std::string());
|
||||
|
||||
if (content_setting == CONTENT_SETTING_ALLOW ||
|
||||
content_setting == CONTENT_SETTING_BLOCK) {
|
||||
NotifyPermissionSet(permission, id, requesting_origin, embedding_origin,
|
||||
callback, false /* persist */, content_setting);
|
||||
return;
|
||||
}
|
||||
|
||||
QueryPermission(
|
||||
permission, id, requesting_origin, embedding_origin,
|
||||
base::Bind(&CefPermissionContext::NotifyPermissionSet,
|
||||
weak_ptr_factory_.GetWeakPtr(), permission, id,
|
||||
requesting_origin, embedding_origin, callback,
|
||||
false /* persist */));
|
||||
}
|
||||
|
||||
void CefPermissionContext::QueryPermission(
|
||||
content::PermissionType permission,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const PermissionDecidedCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
DCHECK(permission == content::PermissionType::GEOLOCATION);
|
||||
|
||||
bool proceed = false;
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser =
|
||||
CefBrowserHostImpl::GetBrowserForFrame(id.render_process_id(),
|
||||
id.render_frame_id());
|
||||
if (browser.get()) {
|
||||
CefRefPtr<CefClient> client = browser->GetClient();
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefGeolocationHandler> handler =
|
||||
client->GetGeolocationHandler();
|
||||
if (handler.get()) {
|
||||
CefRefPtr<CefGeolocationCallbackImpl> callbackImpl(
|
||||
new CefGeolocationCallbackImpl(callback));
|
||||
|
||||
// Notify the handler.
|
||||
proceed = handler->OnRequestGeolocationPermission(
|
||||
browser.get(), requesting_origin.spec(), id.request_id(),
|
||||
callbackImpl.get());
|
||||
if (!proceed)
|
||||
callbackImpl->Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!proceed) {
|
||||
// Disallow geolocation access by default.
|
||||
callback.Run(CONTENT_SETTING_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
void CefPermissionContext::NotifyPermissionSet(
|
||||
content::PermissionType permission,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const BrowserPermissionCallback& callback,
|
||||
bool persist,
|
||||
ContentSetting content_setting) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
if (persist) {
|
||||
UpdateContentSetting(permission, requesting_origin, embedding_origin,
|
||||
content_setting);
|
||||
}
|
||||
|
||||
if (content_setting == CONTENT_SETTING_DEFAULT) {
|
||||
content_setting =
|
||||
profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
|
||||
permission_util::PermissionTypeToContentSetting(permission),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
DCHECK_NE(content_setting, CONTENT_SETTING_DEFAULT);
|
||||
callback.Run(content_setting);
|
||||
}
|
||||
|
||||
void CefPermissionContext::UpdateContentSetting(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
ContentSetting content_setting) {
|
||||
DCHECK_EQ(requesting_origin, requesting_origin.GetOrigin());
|
||||
DCHECK_EQ(embedding_origin, embedding_origin.GetOrigin());
|
||||
DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
|
||||
content_setting == CONTENT_SETTING_BLOCK);
|
||||
|
||||
profile_->GetHostContentSettingsMap()->SetContentSetting(
|
||||
ContentSettingsPattern::FromURLNoWildcard(requesting_origin),
|
||||
ContentSettingsPattern::FromURLNoWildcard(embedding_origin),
|
||||
permission_util::PermissionTypeToContentSetting(permission),
|
||||
std::string(),
|
||||
content_setting);
|
||||
}
|
99
libcef/browser/permissions/permission_context.h
Normal file
99
libcef/browser/permissions/permission_context.h
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright 2015 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_H_
|
||||
#define CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_H_
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "chrome/browser/permissions/permission_request_id.h"
|
||||
#include "components/content_settings/core/common/content_settings.h"
|
||||
|
||||
class CefBrowserContext;
|
||||
|
||||
namespace content {
|
||||
enum class PermissionType;
|
||||
class WebContents;
|
||||
}; // namespace content
|
||||
|
||||
// Based on chrome/browser/permissions/permission_context_base.h
|
||||
class CefPermissionContext {
|
||||
public:
|
||||
explicit CefPermissionContext(CefBrowserContext* profile);
|
||||
|
||||
using BrowserPermissionCallback = base::Callback<void(ContentSetting)>;
|
||||
using PermissionDecidedCallback = base::Callback<void(ContentSetting)>;
|
||||
|
||||
// Returns true if support exists for querying the embedder about the
|
||||
// specified permission type.
|
||||
bool SupportsPermission(content::PermissionType permission);
|
||||
|
||||
// The renderer is requesting permission to push messages.
|
||||
// When the answer to a permission request has been determined, |callback|
|
||||
// should be called with the result.
|
||||
void RequestPermission(content::PermissionType permission,
|
||||
content::WebContents* web_contents,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_frame,
|
||||
bool user_gesture,
|
||||
const BrowserPermissionCallback& callback);
|
||||
|
||||
// Withdraw an existing permission request, no op if the permission request
|
||||
// was already cancelled by some other means.
|
||||
void CancelPermissionRequest(content::PermissionType permission,
|
||||
content::WebContents* web_contents,
|
||||
const PermissionRequestID& id);
|
||||
|
||||
// Resets the permission to its default value.
|
||||
void ResetPermission(content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin);
|
||||
|
||||
// Returns whether the permission has been granted, denied...
|
||||
ContentSetting GetPermissionStatus(content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) const;
|
||||
|
||||
private:
|
||||
// Decide whether the permission should be granted.
|
||||
// Calls PermissionDecided if permission can be decided non-interactively,
|
||||
// or NotifyPermissionSet if permission decided by presenting an infobar.
|
||||
void DecidePermission(content::PermissionType permission,
|
||||
content::WebContents* web_contents,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
bool user_gesture,
|
||||
const BrowserPermissionCallback& callback);
|
||||
|
||||
void QueryPermission(content::PermissionType permission,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const PermissionDecidedCallback& callback);
|
||||
|
||||
void NotifyPermissionSet(content::PermissionType permission,
|
||||
const PermissionRequestID& id,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const BrowserPermissionCallback& callback,
|
||||
bool persist,
|
||||
ContentSetting content_setting);
|
||||
|
||||
// Store the decided permission as a content setting.
|
||||
void UpdateContentSetting(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
ContentSetting content_setting);
|
||||
|
||||
CefBrowserContext* profile_;
|
||||
|
||||
base::WeakPtrFactory<CefPermissionContext> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefPermissionContext);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_H_
|
382
libcef/browser/permissions/permission_manager.cc
Normal file
382
libcef/browser/permissions/permission_manager.cc
Normal file
@@ -0,0 +1,382 @@
|
||||
// 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 "libcef/browser/permissions/permission_manager.h"
|
||||
|
||||
#include "libcef/browser/browser_context.h"
|
||||
#include "libcef/browser/permissions/permission_util.h"
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
#include "content/public/browser/permission_type.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
using content::PermissionStatus;
|
||||
using content::PermissionType;
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper method to convert ContentSetting to PermissionStatus.
|
||||
PermissionStatus ContentSettingToPermissionStatus(ContentSetting setting) {
|
||||
switch (setting) {
|
||||
case CONTENT_SETTING_ALLOW:
|
||||
case CONTENT_SETTING_SESSION_ONLY:
|
||||
return content::PERMISSION_STATUS_GRANTED;
|
||||
case CONTENT_SETTING_BLOCK:
|
||||
return content::PERMISSION_STATUS_DENIED;
|
||||
case CONTENT_SETTING_ASK:
|
||||
return content::PERMISSION_STATUS_ASK;
|
||||
case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
|
||||
case CONTENT_SETTING_DEFAULT:
|
||||
case CONTENT_SETTING_NUM_SETTINGS:
|
||||
break;
|
||||
}
|
||||
|
||||
NOTREACHED();
|
||||
return content::PERMISSION_STATUS_DENIED;
|
||||
}
|
||||
|
||||
// Helper method to convert PermissionStatus to ContentSetting.
|
||||
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;
|
||||
}
|
||||
|
||||
NOTREACHED();
|
||||
return CONTENT_SETTING_BLOCK;
|
||||
}
|
||||
|
||||
// Wrap a callback taking a PermissionStatus to pass it as a callback taking a
|
||||
// ContentSetting.
|
||||
void ContentSettingToPermissionStatusCallbackWrapper(
|
||||
const base::Callback<void(PermissionStatus)>& callback,
|
||||
ContentSetting setting) {
|
||||
callback.Run(ContentSettingToPermissionStatus(setting));
|
||||
}
|
||||
|
||||
// Returns whether the permission has a constant PermissionStatus value (i.e.
|
||||
// always approved or always denied).
|
||||
bool IsConstantPermission(PermissionType type) {
|
||||
switch (type) {
|
||||
case PermissionType::MIDI:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void PermissionRequestResponseCallbackWrapper(
|
||||
const base::Callback<void(PermissionStatus)>& callback,
|
||||
const std::vector<PermissionStatus>& vector) {
|
||||
DCHECK_EQ(vector.size(), 1ul);
|
||||
callback.Run(vector[0]);
|
||||
}
|
||||
|
||||
// Function used for handling permission types which do not change their
|
||||
// value i.e. they are always approved or always denied etc.
|
||||
// CONTENT_SETTING_DEFAULT is returned if the permission needs further handling.
|
||||
// This function should only be called when IsConstantPermission has returned
|
||||
// true for the PermissionType.
|
||||
ContentSetting GetContentSettingForConstantPermission(PermissionType type) {
|
||||
DCHECK(IsConstantPermission(type));
|
||||
switch (type) {
|
||||
case PermissionType::MIDI:
|
||||
return CONTENT_SETTING_ALLOW;
|
||||
default:
|
||||
return CONTENT_SETTING_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) {
|
||||
return ContentSettingToPermissionStatus(
|
||||
GetContentSettingForConstantPermission(type));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class CefPermissionManager::PendingRequest {
|
||||
public:
|
||||
PendingRequest(content::RenderFrameHost* render_frame_host,
|
||||
const std::vector<PermissionType> permissions,
|
||||
const base::Callback<void(
|
||||
const std::vector<PermissionStatus>&)>& callback)
|
||||
: render_process_id_(render_frame_host->GetProcess()->GetID()),
|
||||
render_frame_id_(render_frame_host->GetRoutingID()),
|
||||
callback_(callback),
|
||||
permissions_(permissions),
|
||||
results_(permissions.size(), content::PERMISSION_STATUS_DENIED),
|
||||
remaining_results_(permissions.size()) {
|
||||
}
|
||||
|
||||
void SetPermissionStatus(int permission_id, PermissionStatus status) {
|
||||
DCHECK(!IsComplete());
|
||||
|
||||
results_[permission_id] = status;
|
||||
--remaining_results_;
|
||||
}
|
||||
|
||||
bool IsComplete() const {
|
||||
return remaining_results_ == 0;
|
||||
}
|
||||
|
||||
int render_process_id() const { return render_process_id_; }
|
||||
int render_frame_id() const { return render_frame_id_; }
|
||||
|
||||
const base::Callback<void(const std::vector<PermissionStatus>&)>
|
||||
callback() const {
|
||||
return callback_;
|
||||
}
|
||||
|
||||
std::vector<PermissionType> permissions() const {
|
||||
return permissions_;
|
||||
}
|
||||
|
||||
std::vector<PermissionStatus> results() const {
|
||||
return results_;
|
||||
}
|
||||
|
||||
private:
|
||||
int render_process_id_;
|
||||
int render_frame_id_;
|
||||
const base::Callback<void(const std::vector<PermissionStatus>&)> callback_;
|
||||
std::vector<PermissionType> permissions_;
|
||||
std::vector<PermissionStatus> results_;
|
||||
size_t remaining_results_;
|
||||
};
|
||||
|
||||
struct CefPermissionManager::Subscription {
|
||||
PermissionType permission;
|
||||
GURL requesting_origin;
|
||||
GURL embedding_origin;
|
||||
base::Callback<void(PermissionStatus)> callback;
|
||||
ContentSetting current_value;
|
||||
};
|
||||
|
||||
CefPermissionManager::CefPermissionManager(CefBrowserContext* profile)
|
||||
: profile_(profile),
|
||||
context_(profile),
|
||||
weak_ptr_factory_(this) {
|
||||
}
|
||||
|
||||
CefPermissionManager::~CefPermissionManager() {
|
||||
if (!subscriptions_.IsEmpty())
|
||||
profile_->GetHostContentSettingsMap()->RemoveObserver(this);
|
||||
}
|
||||
|
||||
int CefPermissionManager::RequestPermission(
|
||||
PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
const base::Callback<void(PermissionStatus)>& callback) {
|
||||
return RequestPermissions(
|
||||
std::vector<PermissionType>(1, permission),
|
||||
render_frame_host,
|
||||
requesting_origin,
|
||||
user_gesture,
|
||||
base::Bind(&PermissionRequestResponseCallbackWrapper, callback));
|
||||
}
|
||||
|
||||
int CefPermissionManager::RequestPermissions(
|
||||
const std::vector<PermissionType>& permissions,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
const base::Callback<void(
|
||||
const std::vector<PermissionStatus>&)>& callback) {
|
||||
if (permissions.empty()) {
|
||||
callback.Run(std::vector<PermissionStatus>());
|
||||
return kNoPendingOperation;
|
||||
}
|
||||
|
||||
content::WebContents* web_contents =
|
||||
content::WebContents::FromRenderFrameHost(render_frame_host);
|
||||
GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin();
|
||||
|
||||
PendingRequest* pending_request = new PendingRequest(
|
||||
render_frame_host, permissions, callback);
|
||||
int request_id = pending_requests_.Add(pending_request);
|
||||
|
||||
const PermissionRequestID request(render_frame_host, request_id);
|
||||
|
||||
for (size_t i = 0; i < permissions.size(); ++i) {
|
||||
const PermissionType permission = permissions[i];
|
||||
|
||||
if (IsConstantPermission(permission) ||
|
||||
!context_.SupportsPermission(permission)) {
|
||||
OnPermissionsRequestResponseStatus(request_id, i,
|
||||
GetPermissionStatus(permission, requesting_origin, embedding_origin));
|
||||
continue;
|
||||
}
|
||||
|
||||
context_.RequestPermission(
|
||||
permission, web_contents, request, requesting_origin, user_gesture,
|
||||
base::Bind(&ContentSettingToPermissionStatusCallbackWrapper,
|
||||
base::Bind(
|
||||
&CefPermissionManager::OnPermissionsRequestResponseStatus,
|
||||
weak_ptr_factory_.GetWeakPtr(), request_id, i)));
|
||||
}
|
||||
|
||||
// The request might have been resolved already.
|
||||
if (!pending_requests_.Lookup(request_id))
|
||||
return kNoPendingOperation;
|
||||
|
||||
return request_id;
|
||||
}
|
||||
|
||||
void CefPermissionManager::OnPermissionsRequestResponseStatus(
|
||||
int request_id,
|
||||
int permission_id,
|
||||
PermissionStatus status) {
|
||||
PendingRequest* pending_request = pending_requests_.Lookup(request_id);
|
||||
pending_request->SetPermissionStatus(permission_id, status);
|
||||
|
||||
if (!pending_request->IsComplete())
|
||||
return;
|
||||
|
||||
pending_request->callback().Run(pending_request->results());
|
||||
pending_requests_.Remove(request_id);
|
||||
}
|
||||
|
||||
void CefPermissionManager::CancelPermissionRequest(int request_id) {
|
||||
PendingRequest* pending_request = pending_requests_.Lookup(request_id);
|
||||
if (!pending_request)
|
||||
return;
|
||||
|
||||
content::RenderFrameHost* render_frame_host =
|
||||
content::RenderFrameHost::FromID(pending_request->render_process_id(),
|
||||
pending_request->render_frame_id());
|
||||
DCHECK(render_frame_host);
|
||||
content::WebContents* web_contents =
|
||||
content::WebContents::FromRenderFrameHost(render_frame_host);
|
||||
DCHECK(web_contents);
|
||||
|
||||
const PermissionRequestID request(pending_request->render_process_id(),
|
||||
pending_request->render_frame_id(),
|
||||
request_id);
|
||||
for (PermissionType permission : pending_request->permissions()) {
|
||||
if (!context_.SupportsPermission(permission))
|
||||
continue;
|
||||
context_.CancelPermissionRequest(permission, web_contents, request);
|
||||
}
|
||||
pending_requests_.Remove(request_id);
|
||||
}
|
||||
|
||||
void CefPermissionManager::ResetPermission(PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
if (!context_.SupportsPermission(permission))
|
||||
return;
|
||||
context_.ResetPermission(permission, requesting_origin, embedding_origin);
|
||||
}
|
||||
|
||||
PermissionStatus CefPermissionManager::GetPermissionStatus(
|
||||
PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
if (IsConstantPermission(permission))
|
||||
return GetPermissionStatusForConstantPermission(permission);
|
||||
|
||||
if (!context_.SupportsPermission(permission))
|
||||
return content::PERMISSION_STATUS_DENIED;
|
||||
|
||||
return ContentSettingToPermissionStatus(
|
||||
context_.GetPermissionStatus(permission, requesting_origin,
|
||||
embedding_origin));
|
||||
}
|
||||
|
||||
void CefPermissionManager::RegisterPermissionUsage(
|
||||
PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
// This is required because constant permissions don't have a
|
||||
// ContentSettingsType.
|
||||
if (IsConstantPermission(permission))
|
||||
return;
|
||||
|
||||
profile_->GetHostContentSettingsMap()->UpdateLastUsage(
|
||||
requesting_origin,
|
||||
embedding_origin,
|
||||
permission_util::PermissionTypeToContentSetting(permission));
|
||||
}
|
||||
|
||||
int CefPermissionManager::SubscribePermissionStatusChange(
|
||||
PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const base::Callback<void(PermissionStatus)>& callback) {
|
||||
if (subscriptions_.IsEmpty())
|
||||
profile_->GetHostContentSettingsMap()->AddObserver(this);
|
||||
|
||||
Subscription* subscription = new Subscription();
|
||||
subscription->permission = permission;
|
||||
subscription->requesting_origin = requesting_origin;
|
||||
subscription->embedding_origin = embedding_origin;
|
||||
subscription->callback = callback;
|
||||
|
||||
subscription->current_value = PermissionStatusToContentSetting(
|
||||
GetPermissionStatus(permission,
|
||||
subscription->requesting_origin,
|
||||
subscription->embedding_origin));
|
||||
|
||||
return subscriptions_.Add(subscription);
|
||||
}
|
||||
|
||||
void CefPermissionManager::UnsubscribePermissionStatusChange(
|
||||
int subscription_id) {
|
||||
// Whether |subscription_id| is known will be checked by the Remove() call.
|
||||
subscriptions_.Remove(subscription_id);
|
||||
|
||||
if (subscriptions_.IsEmpty())
|
||||
profile_->GetHostContentSettingsMap()->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void CefPermissionManager::OnContentSettingChanged(
|
||||
const ContentSettingsPattern& primary_pattern,
|
||||
const ContentSettingsPattern& secondary_pattern,
|
||||
ContentSettingsType content_type,
|
||||
std::string resource_identifier) {
|
||||
std::list<base::Closure> callbacks;
|
||||
|
||||
for (SubscriptionsMap::iterator iter(&subscriptions_);
|
||||
!iter.IsAtEnd(); iter.Advance()) {
|
||||
Subscription* subscription = iter.GetCurrentValue();
|
||||
if (permission_util::PermissionTypeToContentSetting(
|
||||
subscription->permission) != content_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (primary_pattern.IsValid() &&
|
||||
!primary_pattern.Matches(subscription->requesting_origin))
|
||||
continue;
|
||||
if (secondary_pattern.IsValid() &&
|
||||
!secondary_pattern.Matches(subscription->embedding_origin))
|
||||
continue;
|
||||
|
||||
ContentSetting new_value = PermissionStatusToContentSetting(
|
||||
GetPermissionStatus(subscription->permission,
|
||||
subscription->requesting_origin,
|
||||
subscription->embedding_origin));
|
||||
if (subscription->current_value == new_value)
|
||||
continue;
|
||||
|
||||
subscription->current_value = new_value;
|
||||
|
||||
// Add the callback to |callbacks| which will be run after the loop to
|
||||
// prevent re-entrance issues.
|
||||
callbacks.push_back(
|
||||
base::Bind(subscription->callback,
|
||||
ContentSettingToPermissionStatus(new_value)));
|
||||
}
|
||||
|
||||
for (const auto& callback : callbacks)
|
||||
callback.Run();
|
||||
}
|
100
libcef/browser/permissions/permission_manager.h
Normal file
100
libcef/browser/permissions/permission_manager.h
Normal file
@@ -0,0 +1,100 @@
|
||||
// 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.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_MANAGER_H_
|
||||
#define CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_MANAGER_H_
|
||||
|
||||
#include "libcef/browser/permissions/permission_context.h"
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "base/id_map.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "components/content_settings/core/browser/content_settings_observer.h"
|
||||
#include "components/content_settings/core/common/content_settings.h"
|
||||
#include "components/keyed_service/core/keyed_service.h"
|
||||
#include "content/public/browser/permission_manager.h"
|
||||
|
||||
class CefBrowserContext;
|
||||
|
||||
namespace content {
|
||||
enum class PermissionType;
|
||||
class WebContents;
|
||||
}; // namespace content
|
||||
|
||||
// Implementation based on chrome/browser/permissions/permission_manager.h
|
||||
class CefPermissionManager : public KeyedService,
|
||||
public content::PermissionManager,
|
||||
public content_settings::Observer {
|
||||
public:
|
||||
explicit CefPermissionManager(CefBrowserContext* profile);
|
||||
~CefPermissionManager() override;
|
||||
|
||||
// content::CefPermissionManager implementation.
|
||||
int RequestPermission(
|
||||
content::PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
const base::Callback<void(content::PermissionStatus)>& callback) override;
|
||||
int RequestPermissions(
|
||||
const std::vector<content::PermissionType>& permissions,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
const base::Callback<void(
|
||||
const std::vector<content::PermissionStatus>&)>& callback) override;
|
||||
void CancelPermissionRequest(int request_id) override;
|
||||
void ResetPermission(content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
content::PermissionStatus GetPermissionStatus(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
void RegisterPermissionUsage(content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
int SubscribePermissionStatusChange(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const base::Callback<void(content::PermissionStatus)>& callback) override;
|
||||
void UnsubscribePermissionStatusChange(int subscription_id) override;
|
||||
|
||||
private:
|
||||
class PendingRequest;
|
||||
using PendingRequestsMap = IDMap<PendingRequest, IDMapOwnPointer>;
|
||||
|
||||
struct Subscription;
|
||||
using SubscriptionsMap = IDMap<Subscription, IDMapOwnPointer>;
|
||||
|
||||
// Called when a permission was decided for a given PendingRequest. The
|
||||
// PendingRequest is identified by its |request_id| and the permission is
|
||||
// identified by its |permission_id|. If the PendingRequest contains more than
|
||||
// one permission, it will wait for the remaining permissions to be resolved.
|
||||
// When all the permissions have been resolved, the PendingRequest's callback
|
||||
// is run.
|
||||
void OnPermissionsRequestResponseStatus(
|
||||
int request_id,
|
||||
int permission_id,
|
||||
content::PermissionStatus status);
|
||||
|
||||
// content_settings::Observer implementation.
|
||||
void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
|
||||
const ContentSettingsPattern& secondary_pattern,
|
||||
ContentSettingsType content_type,
|
||||
std::string resource_identifier) override;
|
||||
|
||||
CefBrowserContext* profile_;
|
||||
PendingRequestsMap pending_requests_;
|
||||
SubscriptionsMap subscriptions_;
|
||||
CefPermissionContext context_;
|
||||
|
||||
base::WeakPtrFactory<CefPermissionManager> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefPermissionManager);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_MANAGER_H_
|
49
libcef/browser/permissions/permission_util.cc
Normal file
49
libcef/browser/permissions/permission_util.cc
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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 "libcef/browser/permissions/permission_util.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
using content::PermissionType;
|
||||
|
||||
namespace permission_util {
|
||||
|
||||
ContentSettingsType PermissionTypeToContentSetting(PermissionType permission) {
|
||||
switch (permission) {
|
||||
case PermissionType::MIDI_SYSEX:
|
||||
return CONTENT_SETTINGS_TYPE_MIDI_SYSEX;
|
||||
case PermissionType::PUSH_MESSAGING:
|
||||
return CONTENT_SETTINGS_TYPE_PUSH_MESSAGING;
|
||||
case PermissionType::NOTIFICATIONS:
|
||||
return CONTENT_SETTINGS_TYPE_NOTIFICATIONS;
|
||||
case PermissionType::GEOLOCATION:
|
||||
return CONTENT_SETTINGS_TYPE_GEOLOCATION;
|
||||
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
|
||||
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
|
||||
return CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER;
|
||||
#else
|
||||
NOTIMPLEMENTED();
|
||||
break;
|
||||
#endif
|
||||
case PermissionType::DURABLE_STORAGE:
|
||||
return CONTENT_SETTINGS_TYPE_DURABLE_STORAGE;
|
||||
case PermissionType::MIDI:
|
||||
// This will hit the NOTREACHED below.
|
||||
break;
|
||||
case PermissionType::AUDIO_CAPTURE:
|
||||
return CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC;
|
||||
case PermissionType::VIDEO_CAPTURE:
|
||||
return CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA;
|
||||
case PermissionType::NUM:
|
||||
// This will hit the NOTREACHED below.
|
||||
break;
|
||||
}
|
||||
|
||||
NOTREACHED() << "Unknown content setting for permission "
|
||||
<< static_cast<int>(permission);
|
||||
return CONTENT_SETTINGS_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
} // namespace permission_util
|
19
libcef/browser/permissions/permission_util.h
Normal file
19
libcef/browser/permissions/permission_util.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_UTIL_H_
|
||||
#define CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_UTIL_H_
|
||||
|
||||
#include "components/content_settings/core/common/content_settings_types.h"
|
||||
#include "content/public/browser/permission_type.h"
|
||||
|
||||
namespace permission_util {
|
||||
|
||||
// Helper method to convert PermissionType to ContentSettingType.
|
||||
ContentSettingsType PermissionTypeToContentSetting(
|
||||
content::PermissionType permission);
|
||||
|
||||
} // namespace permission_util
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_PERMISSIONS_PERMISSION_UTIL_H_
|
Reference in New Issue
Block a user