mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			291 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			291 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright (c) 2011 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/origin_whitelist_impl.h"
 | 
						|
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
#include "include/cef_origin_whitelist.h"
 | 
						|
#include "libcef/browser/context.h"
 | 
						|
#include "libcef/browser/thread_util.h"
 | 
						|
#include "libcef/common/cef_messages.h"
 | 
						|
 | 
						|
#include "base/bind.h"
 | 
						|
#include "base/lazy_instance.h"
 | 
						|
#include "base/synchronization/lock.h"
 | 
						|
#include "content/public/browser/render_process_host.h"
 | 
						|
#include "url/gurl.h"
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
// Class that manages cross-origin whitelist registrations.
 | 
						|
class CefOriginWhitelistManager {
 | 
						|
 public:
 | 
						|
  CefOriginWhitelistManager() {}
 | 
						|
 | 
						|
  // Retrieve the singleton instance.
 | 
						|
  static CefOriginWhitelistManager* GetInstance();
 | 
						|
 | 
						|
  bool AddOriginEntry(const std::string& source_origin,
 | 
						|
                      const std::string& target_protocol,
 | 
						|
                      const std::string& target_domain,
 | 
						|
                      bool allow_target_subdomains) {
 | 
						|
    Cef_CrossOriginWhiteListEntry_Params info;
 | 
						|
    info.source_origin = source_origin;
 | 
						|
    info.target_protocol = target_protocol;
 | 
						|
    info.target_domain = target_domain;
 | 
						|
    info.allow_target_subdomains = allow_target_subdomains;
 | 
						|
 | 
						|
    {
 | 
						|
      base::AutoLock lock_scope(lock_);
 | 
						|
 | 
						|
      // Verify that the origin entry doesn't already exist.
 | 
						|
      OriginList::const_iterator it = origin_list_.begin();
 | 
						|
      for (; it != origin_list_.end(); ++it) {
 | 
						|
        if (IsEqual(*it, info))
 | 
						|
          return false;
 | 
						|
      }
 | 
						|
 | 
						|
      origin_list_.push_back(info);
 | 
						|
    }
 | 
						|
 | 
						|
    SendModifyCrossOriginWhitelistEntry(true, info);
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  bool RemoveOriginEntry(const std::string& source_origin,
 | 
						|
                         const std::string& target_protocol,
 | 
						|
                         const std::string& target_domain,
 | 
						|
                         bool allow_target_subdomains) {
 | 
						|
    Cef_CrossOriginWhiteListEntry_Params info;
 | 
						|
    info.source_origin = source_origin;
 | 
						|
    info.target_protocol = target_protocol;
 | 
						|
    info.target_domain = target_domain;
 | 
						|
    info.allow_target_subdomains = allow_target_subdomains;
 | 
						|
 | 
						|
    bool found = false;
 | 
						|
 | 
						|
    {
 | 
						|
      base::AutoLock lock_scope(lock_);
 | 
						|
 | 
						|
      OriginList::iterator it = origin_list_.begin();
 | 
						|
      for (; it != origin_list_.end(); ++it) {
 | 
						|
        if (IsEqual(*it, info)) {
 | 
						|
          origin_list_.erase(it);
 | 
						|
          found = true;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!found)
 | 
						|
      return false;
 | 
						|
 | 
						|
    SendModifyCrossOriginWhitelistEntry(false, info);
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  void ClearOrigins() {
 | 
						|
    {
 | 
						|
      base::AutoLock lock_scope(lock_);
 | 
						|
      origin_list_.clear();
 | 
						|
    }
 | 
						|
 | 
						|
    SendClearCrossOriginWhitelist();
 | 
						|
  }
 | 
						|
 | 
						|
  void GetCrossOriginWhitelistEntries(
 | 
						|
      std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries) {
 | 
						|
    base::AutoLock lock_scope(lock_);
 | 
						|
 | 
						|
    if (origin_list_.empty())
 | 
						|
      return;
 | 
						|
    entries->insert(entries->end(), origin_list_.begin(), origin_list_.end());
 | 
						|
  }
 | 
						|
 | 
						|
 private:
 | 
						|
  // Send the modify cross-origin whitelist entry message to all currently
 | 
						|
  // existing hosts.
 | 
						|
  static void SendModifyCrossOriginWhitelistEntry(
 | 
						|
      bool add,
 | 
						|
      Cef_CrossOriginWhiteListEntry_Params& params) {
 | 
						|
    CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
    content::RenderProcessHost::iterator i(
 | 
						|
        content::RenderProcessHost::AllHostsIterator());
 | 
						|
    for (; !i.IsAtEnd(); i.Advance()) {
 | 
						|
      i.GetCurrentValue()->Send(
 | 
						|
          new CefProcessMsg_ModifyCrossOriginWhitelistEntry(add, params));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Send the clear cross-origin whitelists message to all currently existing
 | 
						|
  // hosts.
 | 
						|
  static void SendClearCrossOriginWhitelist() {
 | 
						|
    CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
    content::RenderProcessHost::iterator i(
 | 
						|
        content::RenderProcessHost::AllHostsIterator());
 | 
						|
    for (; !i.IsAtEnd(); i.Advance()) {
 | 
						|
      i.GetCurrentValue()->Send(new CefProcessMsg_ClearCrossOriginWhitelist);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  static bool IsEqual(const Cef_CrossOriginWhiteListEntry_Params& param1,
 | 
						|
                      const Cef_CrossOriginWhiteListEntry_Params& param2) {
 | 
						|
    return (param1.source_origin == param2.source_origin &&
 | 
						|
            param1.target_protocol == param2.target_protocol &&
 | 
						|
            param1.target_domain == param2.target_domain &&
 | 
						|
            param1.allow_target_subdomains == param2.allow_target_subdomains);
 | 
						|
  }
 | 
						|
 | 
						|
  base::Lock lock_;
 | 
						|
 | 
						|
  // List of registered origins. Access must be protected by |lock_|.
 | 
						|
  typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> OriginList;
 | 
						|
  OriginList origin_list_;
 | 
						|
 | 
						|
  DISALLOW_COPY_AND_ASSIGN(CefOriginWhitelistManager);
 | 
						|
};
 | 
						|
 | 
						|
base::LazyInstance<CefOriginWhitelistManager>::Leaky g_manager =
 | 
						|
    LAZY_INSTANCE_INITIALIZER;
 | 
						|
 | 
						|
CefOriginWhitelistManager* CefOriginWhitelistManager::GetInstance() {
 | 
						|
  return g_manager.Pointer();
 | 
						|
}
 | 
						|
 | 
						|
bool IsMatch(const GURL& source_origin,
 | 
						|
             const GURL& target_origin,
 | 
						|
             const Cef_CrossOriginWhiteListEntry_Params& param) {
 | 
						|
  if (source_origin.GetOrigin() != GURL(param.source_origin)) {
 | 
						|
    // Source origin does not match.
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (target_origin.scheme() != param.target_protocol) {
 | 
						|
    // Target scheme does not match.
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (param.allow_target_subdomains) {
 | 
						|
    if (param.target_domain.empty()) {
 | 
						|
      // Any domain will match.
 | 
						|
      return true;
 | 
						|
    } else {
 | 
						|
      // Match sub-domains.
 | 
						|
      return target_origin.DomainIs(param.target_domain.c_str());
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // Match full domain.
 | 
						|
    return (target_origin.host() == param.target_domain);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace
 | 
						|
 | 
						|
bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin,
 | 
						|
                                     const CefString& target_protocol,
 | 
						|
                                     const CefString& target_domain,
 | 
						|
                                     bool allow_target_subdomains) {
 | 
						|
  // Verify that the context is in a valid state.
 | 
						|
  if (!CONTEXT_STATE_VALID()) {
 | 
						|
    NOTREACHED();
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  std::string source_url = source_origin;
 | 
						|
  GURL gurl = GURL(source_url);
 | 
						|
  if (gurl.is_empty() || !gurl.is_valid()) {
 | 
						|
    NOTREACHED() << "Invalid source_origin URL: " << source_url;
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    return CefOriginWhitelistManager::GetInstance()->AddOriginEntry(
 | 
						|
        source_origin, target_protocol, target_domain, allow_target_subdomains);
 | 
						|
  } else {
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_UIT,
 | 
						|
        base::Bind(base::IgnoreResult(&CefAddCrossOriginWhitelistEntry),
 | 
						|
                   source_origin, target_protocol, target_domain,
 | 
						|
                   allow_target_subdomains));
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin,
 | 
						|
                                        const CefString& target_protocol,
 | 
						|
                                        const CefString& target_domain,
 | 
						|
                                        bool allow_target_subdomains) {
 | 
						|
  // Verify that the context is in a valid state.
 | 
						|
  if (!CONTEXT_STATE_VALID()) {
 | 
						|
    NOTREACHED();
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  std::string source_url = source_origin;
 | 
						|
  GURL gurl = GURL(source_url);
 | 
						|
  if (gurl.is_empty() || !gurl.is_valid()) {
 | 
						|
    NOTREACHED() << "Invalid source_origin URL: " << source_url;
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    return CefOriginWhitelistManager::GetInstance()->RemoveOriginEntry(
 | 
						|
        source_origin, target_protocol, target_domain, allow_target_subdomains);
 | 
						|
  } else {
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_UIT,
 | 
						|
        base::Bind(base::IgnoreResult(&CefRemoveCrossOriginWhitelistEntry),
 | 
						|
                   source_origin, target_protocol, target_domain,
 | 
						|
                   allow_target_subdomains));
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool CefClearCrossOriginWhitelist() {
 | 
						|
  // Verify that the context is in a valid state.
 | 
						|
  if (!CONTEXT_STATE_VALID()) {
 | 
						|
    NOTREACHED();
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    CefOriginWhitelistManager::GetInstance()->ClearOrigins();
 | 
						|
  } else {
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_UIT, base::Bind(base::IgnoreResult(&CefClearCrossOriginWhitelist)));
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void GetCrossOriginWhitelistEntries(
 | 
						|
    std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries) {
 | 
						|
  CefOriginWhitelistManager::GetInstance()->GetCrossOriginWhitelistEntries(
 | 
						|
      entries);
 | 
						|
}
 | 
						|
 | 
						|
bool HasCrossOriginWhitelistEntry(const GURL& source, const GURL& target) {
 | 
						|
  std::vector<Cef_CrossOriginWhiteListEntry_Params> params;
 | 
						|
  CefOriginWhitelistManager::GetInstance()->GetCrossOriginWhitelistEntries(
 | 
						|
      ¶ms);
 | 
						|
 | 
						|
  if (params.empty())
 | 
						|
    return false;
 | 
						|
 | 
						|
  std::vector<Cef_CrossOriginWhiteListEntry_Params>::const_iterator it =
 | 
						|
      params.begin();
 | 
						|
  for (; it != params.end(); ++it) {
 | 
						|
    if (IsMatch(source, target, *it))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 |