mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			266 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// 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/permission_type.h"
 | 
						|
#include "content/public/browser/web_contents.h"
 | 
						|
#include "content/public/common/origin_util.h"
 | 
						|
#include "device/geolocation/geolocation_provider.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) {
 | 
						|
          device::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,
 | 
						|
    const BrowserPermissionCallback& callback) {
 | 
						|
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 | 
						|
 | 
						|
  DecidePermission(permission,
 | 
						|
                   web_contents,
 | 
						|
                   id,
 | 
						|
                   requesting_frame.GetOrigin(),
 | 
						|
                   web_contents->GetLastCommittedURL().GetOrigin(),
 | 
						|
                   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()->SetContentSettingCustomScope(
 | 
						|
      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,
 | 
						|
    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()->SetContentSettingCustomScope(
 | 
						|
      ContentSettingsPattern::FromURLNoWildcard(requesting_origin),
 | 
						|
      ContentSettingsPattern::FromURLNoWildcard(embedding_origin),
 | 
						|
      permission_util::PermissionTypeToContentSetting(permission),
 | 
						|
      std::string(),
 | 
						|
      content_setting);
 | 
						|
}
 |