mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			766 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			766 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright (c) 2013 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/request_context_impl.h"
 | 
						|
#include "libcef/browser/browser_context.h"
 | 
						|
#include "libcef/browser/content_browser_client.h"
 | 
						|
#include "libcef/browser/context.h"
 | 
						|
#include "libcef/browser/extensions/extension_system.h"
 | 
						|
#include "libcef/browser/net_service/cookie_manager_impl.h"
 | 
						|
#include "libcef/browser/thread_util.h"
 | 
						|
#include "libcef/common/extensions/extensions_util.h"
 | 
						|
#include "libcef/common/task_runner_impl.h"
 | 
						|
#include "libcef/common/values_impl.h"
 | 
						|
 | 
						|
#include "base/atomic_sequence_num.h"
 | 
						|
#include "base/logging.h"
 | 
						|
#include "base/strings/stringprintf.h"
 | 
						|
#include "components/prefs/pref_service.h"
 | 
						|
#include "content/public/browser/browser_task_traits.h"
 | 
						|
#include "content/public/browser/plugin_service.h"
 | 
						|
#include "content/public/browser/ssl_host_state_delegate.h"
 | 
						|
#include "mojo/public/cpp/bindings/binding.h"
 | 
						|
#include "services/network/public/cpp/resolve_host_client_base.h"
 | 
						|
 | 
						|
using content::BrowserThread;
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
base::AtomicSequenceNumber g_next_id;
 | 
						|
 | 
						|
const char* GetTypeString(base::Value::Type type) {
 | 
						|
  switch (type) {
 | 
						|
    case base::Value::Type::NONE:
 | 
						|
      return "NULL";
 | 
						|
    case base::Value::Type::BOOLEAN:
 | 
						|
      return "BOOLEAN";
 | 
						|
    case base::Value::Type::INTEGER:
 | 
						|
      return "INTEGER";
 | 
						|
    case base::Value::Type::DOUBLE:
 | 
						|
      return "DOUBLE";
 | 
						|
    case base::Value::Type::STRING:
 | 
						|
      return "STRING";
 | 
						|
    case base::Value::Type::BINARY:
 | 
						|
      return "BINARY";
 | 
						|
    case base::Value::Type::DICTIONARY:
 | 
						|
      return "DICTIONARY";
 | 
						|
    case base::Value::Type::LIST:
 | 
						|
      return "LIST";
 | 
						|
    case base::Value::Type::DEAD:
 | 
						|
      return "DEAD";
 | 
						|
  }
 | 
						|
 | 
						|
  NOTREACHED();
 | 
						|
  return "UNKNOWN";
 | 
						|
}
 | 
						|
 | 
						|
// Helper for HostResolver::Resolve.
 | 
						|
struct ResolveHostHelperOld {
 | 
						|
  explicit ResolveHostHelperOld(CefRefPtr<CefResolveCallback> callback)
 | 
						|
      : callback_(callback) {}
 | 
						|
 | 
						|
  void OnResolveCompleted(int result) {
 | 
						|
    std::vector<CefString> resolved_ips;
 | 
						|
    base::Optional<net::AddressList> maybe_address_list =
 | 
						|
        request_->GetAddressResults();
 | 
						|
    if (maybe_address_list) {
 | 
						|
      net::AddressList::const_iterator iter = maybe_address_list->begin();
 | 
						|
      for (; iter != maybe_address_list->end(); ++iter)
 | 
						|
        resolved_ips.push_back(iter->ToStringWithoutPort());
 | 
						|
    }
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_UIT,
 | 
						|
        base::Bind(&CefResolveCallback::OnResolveCompleted, callback_,
 | 
						|
                   static_cast<cef_errorcode_t>(result), resolved_ips));
 | 
						|
 | 
						|
    delete this;
 | 
						|
  }
 | 
						|
 | 
						|
  CefRefPtr<CefResolveCallback> callback_;
 | 
						|
  std::unique_ptr<net::HostResolver::ResolveHostRequest> request_;
 | 
						|
};
 | 
						|
 | 
						|
class ResolveHostHelper : public network::ResolveHostClientBase {
 | 
						|
 public:
 | 
						|
  explicit ResolveHostHelper(CefRefPtr<CefResolveCallback> callback)
 | 
						|
      : callback_(callback), binding_(this) {}
 | 
						|
 | 
						|
  void Start(CefBrowserContext* browser_context, const CefString& origin) {
 | 
						|
    CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
    network::mojom::HostResolverPtrInfo host_resolver_info;
 | 
						|
    browser_context->GetNetworkContext()->CreateHostResolver(
 | 
						|
        base::nullopt, mojo::MakeRequest(&host_resolver_info));
 | 
						|
 | 
						|
    network::mojom::ResolveHostClientPtr client_ptr;
 | 
						|
    binding_.Bind(mojo::MakeRequest(&client_ptr));
 | 
						|
    binding_.set_connection_error_handler(
 | 
						|
        base::BindOnce(&ResolveHostHelper::OnComplete, base::Unretained(this),
 | 
						|
                       net::ERR_FAILED, base::nullopt));
 | 
						|
    host_resolver_ =
 | 
						|
        network::mojom::HostResolverPtr(std::move(host_resolver_info));
 | 
						|
    host_resolver_->ResolveHost(
 | 
						|
        net::HostPortPair::FromURL(GURL(origin.ToString())), nullptr,
 | 
						|
        std::move(client_ptr));
 | 
						|
  }
 | 
						|
 | 
						|
 private:
 | 
						|
  void OnComplete(
 | 
						|
      int result,
 | 
						|
      const base::Optional<net::AddressList>& resolved_addresses) override {
 | 
						|
    CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
    host_resolver_.reset();
 | 
						|
    binding_.Close();
 | 
						|
 | 
						|
    std::vector<CefString> resolved_ips;
 | 
						|
 | 
						|
    if (result == net::OK) {
 | 
						|
      DCHECK(resolved_addresses && !resolved_addresses->empty());
 | 
						|
      for (const auto& value : resolved_addresses.value()) {
 | 
						|
        resolved_ips.push_back(value.ToStringWithoutPort());
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    callback_->OnResolveCompleted(static_cast<cef_errorcode_t>(result),
 | 
						|
                                  resolved_ips);
 | 
						|
    delete this;
 | 
						|
  }
 | 
						|
 | 
						|
  CefRefPtr<CefResolveCallback> callback_;
 | 
						|
 | 
						|
  network::mojom::HostResolverPtr host_resolver_;
 | 
						|
  mojo::Binding<network::mojom::ResolveHostClient> binding_;
 | 
						|
 | 
						|
  DISALLOW_COPY_AND_ASSIGN(ResolveHostHelper);
 | 
						|
};
 | 
						|
 | 
						|
}  // namespace
 | 
						|
 | 
						|
// CefBrowserContext
 | 
						|
 | 
						|
// static
 | 
						|
CefRefPtr<CefRequestContext> CefRequestContext::GetGlobalContext() {
 | 
						|
  // Verify that the context is in a valid state.
 | 
						|
  if (!CONTEXT_STATE_VALID()) {
 | 
						|
    NOTREACHED() << "context not valid";
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  CefRequestContextImpl::Config config;
 | 
						|
  config.is_global = true;
 | 
						|
  return CefRequestContextImpl::GetOrCreateRequestContext(config);
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
CefRefPtr<CefRequestContext> CefRequestContext::CreateContext(
 | 
						|
    const CefRequestContextSettings& settings,
 | 
						|
    CefRefPtr<CefRequestContextHandler> handler) {
 | 
						|
  // Verify that the context is in a valid state.
 | 
						|
  if (!CONTEXT_STATE_VALID()) {
 | 
						|
    NOTREACHED() << "context not valid";
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  CefRequestContextImpl::Config config;
 | 
						|
  config.settings = settings;
 | 
						|
  config.handler = handler;
 | 
						|
  config.unique_id = g_next_id.GetNext();
 | 
						|
  return CefRequestContextImpl::GetOrCreateRequestContext(config);
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
CefRefPtr<CefRequestContext> CefRequestContext::CreateContext(
 | 
						|
    CefRefPtr<CefRequestContext> other,
 | 
						|
    CefRefPtr<CefRequestContextHandler> handler) {
 | 
						|
  // Verify that the context is in a valid state.
 | 
						|
  if (!CONTEXT_STATE_VALID()) {
 | 
						|
    NOTREACHED() << "context not valid";
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!other.get())
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  CefRequestContextImpl::Config config;
 | 
						|
  config.other = static_cast<CefRequestContextImpl*>(other.get());
 | 
						|
  config.handler = handler;
 | 
						|
  config.unique_id = g_next_id.GetNext();
 | 
						|
  return CefRequestContextImpl::GetOrCreateRequestContext(config);
 | 
						|
}
 | 
						|
 | 
						|
// CefRequestContextImpl
 | 
						|
 | 
						|
CefRequestContextImpl::~CefRequestContextImpl() {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  if (browser_context_) {
 | 
						|
    // May result in |browser_context_| being deleted if no other
 | 
						|
    // CefRequestContextImpl are referencing it.
 | 
						|
    browser_context_->RemoveCefRequestContext(this);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
CefRefPtr<CefRequestContextImpl>
 | 
						|
CefRequestContextImpl::CreateGlobalRequestContext(
 | 
						|
    const CefRequestContextSettings& settings) {
 | 
						|
  // Create and initialize the global context immediately.
 | 
						|
  Config config;
 | 
						|
  config.is_global = true;
 | 
						|
  config.settings = settings;
 | 
						|
  CefRefPtr<CefRequestContextImpl> impl = new CefRequestContextImpl(config);
 | 
						|
  impl->Initialize();
 | 
						|
  return impl;
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
CefRefPtr<CefRequestContextImpl>
 | 
						|
CefRequestContextImpl::GetOrCreateForRequestContext(
 | 
						|
    CefRefPtr<CefRequestContext> request_context) {
 | 
						|
  if (request_context.get()) {
 | 
						|
    // Use the context from the provided CefRequestContext.
 | 
						|
    return static_cast<CefRequestContextImpl*>(request_context.get());
 | 
						|
  }
 | 
						|
 | 
						|
  // Use the global context.
 | 
						|
  Config config;
 | 
						|
  config.is_global = true;
 | 
						|
  return CefRequestContextImpl::GetOrCreateRequestContext(config);
 | 
						|
}
 | 
						|
 | 
						|
CefBrowserContext* CefRequestContextImpl::GetBrowserContext() {
 | 
						|
  EnsureBrowserContext();
 | 
						|
  return browser_context();
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::GetBrowserContext(
 | 
						|
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
 | 
						|
    const BrowserContextCallback& callback) {
 | 
						|
  if (!task_runner.get())
 | 
						|
    task_runner = CefTaskRunnerImpl::GetCurrentTaskRunner();
 | 
						|
  GetBrowserContextOnUIThread(task_runner, callback);
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::IsSame(CefRefPtr<CefRequestContext> other) {
 | 
						|
  CefRequestContextImpl* other_impl =
 | 
						|
      static_cast<CefRequestContextImpl*>(other.get());
 | 
						|
  if (!other_impl)
 | 
						|
    return false;
 | 
						|
 | 
						|
  // Compare whether both are the global context.
 | 
						|
  if (config_.is_global && other_impl->config_.is_global)
 | 
						|
    return true;
 | 
						|
 | 
						|
  // Compare CefBrowserContext pointers if one has been associated.
 | 
						|
  if (browser_context() && other_impl->browser_context()) {
 | 
						|
    return (browser_context() == other_impl->browser_context());
 | 
						|
  } else if (browser_context() || other_impl->browser_context()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Otherwise compare unique IDs.
 | 
						|
  return (config_.unique_id == other_impl->config_.unique_id);
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) {
 | 
						|
  CefRequestContextImpl* other_impl =
 | 
						|
      static_cast<CefRequestContextImpl*>(other.get());
 | 
						|
  if (!other_impl)
 | 
						|
    return false;
 | 
						|
 | 
						|
  if (IsSame(other))
 | 
						|
    return true;
 | 
						|
 | 
						|
  CefRefPtr<CefRequestContext> pending_other = config_.other;
 | 
						|
  if (pending_other.get()) {
 | 
						|
    // This object is not initialized but we know what context this object will
 | 
						|
    // share with. Compare to that other context instead.
 | 
						|
    return pending_other->IsSharingWith(other);
 | 
						|
  }
 | 
						|
 | 
						|
  pending_other = other_impl->config_.other;
 | 
						|
  if (pending_other.get()) {
 | 
						|
    // The other object is not initialized but we know what context that object
 | 
						|
    // will share with. Compare to that other context instead.
 | 
						|
    return pending_other->IsSharingWith(this);
 | 
						|
  }
 | 
						|
 | 
						|
  // This or the other object is not initialized. Compare the cache path values.
 | 
						|
  // If both are non-empty and the same then they'll share the same storage.
 | 
						|
  if (config_.settings.cache_path.length > 0 &&
 | 
						|
      other_impl->config_.settings.cache_path.length > 0) {
 | 
						|
    return (
 | 
						|
        base::FilePath(CefString(&config_.settings.cache_path)) ==
 | 
						|
        base::FilePath(CefString(&other_impl->config_.settings.cache_path)));
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::IsGlobal() {
 | 
						|
  return config_.is_global;
 | 
						|
}
 | 
						|
 | 
						|
CefRefPtr<CefRequestContextHandler> CefRequestContextImpl::GetHandler() {
 | 
						|
  return config_.handler;
 | 
						|
}
 | 
						|
 | 
						|
CefString CefRequestContextImpl::GetCachePath() {
 | 
						|
  return CefString(&config_.settings.cache_path);
 | 
						|
}
 | 
						|
 | 
						|
CefRefPtr<CefCookieManager> CefRequestContextImpl::GetCookieManager(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback) {
 | 
						|
  CefRefPtr<CefCookieManagerImpl> cookie_manager = new CefCookieManagerImpl();
 | 
						|
  cookie_manager->Initialize(this, callback);
 | 
						|
  return cookie_manager.get();
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::RegisterSchemeHandlerFactory(
 | 
						|
    const CefString& scheme_name,
 | 
						|
    const CefString& domain_name,
 | 
						|
    CefRefPtr<CefSchemeHandlerFactory> factory) {
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    CEF_POST_TASK(CEF_UIT,
 | 
						|
                  base::BindOnce(
 | 
						|
                      base::IgnoreResult(
 | 
						|
                          &CefRequestContextImpl::RegisterSchemeHandlerFactory),
 | 
						|
                      this, scheme_name, domain_name, factory));
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  browser_context()->RegisterSchemeHandlerFactory(scheme_name, domain_name,
 | 
						|
                                                  factory);
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::ClearSchemeHandlerFactories() {
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_UIT,
 | 
						|
        base::BindOnce(base::IgnoreResult(
 | 
						|
                           &CefRequestContextImpl::ClearSchemeHandlerFactories),
 | 
						|
                       this));
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  browser_context()->ClearSchemeHandlerFactories();
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::PurgePluginListCache(bool reload_pages) {
 | 
						|
  GetBrowserContext(
 | 
						|
      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
 | 
						|
      base::Bind(&CefRequestContextImpl::PurgePluginListCacheInternal, this,
 | 
						|
                 reload_pages));
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::HasPreference(const CefString& name) {
 | 
						|
  // Verify that this method is being called on the UI thread.
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  PrefService* pref_service = browser_context()->GetPrefs();
 | 
						|
  return (pref_service->FindPreference(name) != NULL);
 | 
						|
}
 | 
						|
 | 
						|
CefRefPtr<CefValue> CefRequestContextImpl::GetPreference(
 | 
						|
    const CefString& name) {
 | 
						|
  // Verify that this method is being called on the UI thread.
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  PrefService* pref_service = browser_context()->GetPrefs();
 | 
						|
  const PrefService::Preference* pref = pref_service->FindPreference(name);
 | 
						|
  if (!pref)
 | 
						|
    return NULL;
 | 
						|
  return new CefValueImpl(pref->GetValue()->DeepCopy());
 | 
						|
}
 | 
						|
 | 
						|
CefRefPtr<CefDictionaryValue> CefRequestContextImpl::GetAllPreferences(
 | 
						|
    bool include_defaults) {
 | 
						|
  // Verify that this method is being called on the UI thread.
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  PrefService* pref_service = browser_context()->GetPrefs();
 | 
						|
 | 
						|
  std::unique_ptr<base::DictionaryValue> values =
 | 
						|
      pref_service->GetPreferenceValues(include_defaults
 | 
						|
                                            ? PrefService::INCLUDE_DEFAULTS
 | 
						|
                                            : PrefService::EXCLUDE_DEFAULTS);
 | 
						|
 | 
						|
  // CefDictionaryValueImpl takes ownership of |values|.
 | 
						|
  return new CefDictionaryValueImpl(values.release(), true, false);
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::CanSetPreference(const CefString& name) {
 | 
						|
  // Verify that this method is being called on the UI thread.
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  PrefService* pref_service = browser_context()->GetPrefs();
 | 
						|
  const PrefService::Preference* pref = pref_service->FindPreference(name);
 | 
						|
  return (pref && pref->IsUserModifiable());
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::SetPreference(const CefString& name,
 | 
						|
                                          CefRefPtr<CefValue> value,
 | 
						|
                                          CefString& error) {
 | 
						|
  // Verify that this method is being called on the UI thread.
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  PrefService* pref_service = browser_context()->GetPrefs();
 | 
						|
 | 
						|
  // The below validation logic should match PrefService::SetUserPrefValue.
 | 
						|
 | 
						|
  const PrefService::Preference* pref = pref_service->FindPreference(name);
 | 
						|
  if (!pref) {
 | 
						|
    error = "Trying to modify an unregistered preference";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!pref->IsUserModifiable()) {
 | 
						|
    error = "Trying to modify a preference that is not user modifiable";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!value.get()) {
 | 
						|
    // Reset the preference to its default value.
 | 
						|
    pref_service->ClearPref(name);
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!value->IsValid()) {
 | 
						|
    error = "A valid value is required";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  CefValueImpl* impl = static_cast<CefValueImpl*>(value.get());
 | 
						|
 | 
						|
  CefValueImpl::ScopedLockedValue scoped_locked_value(impl);
 | 
						|
  base::Value* impl_value = impl->GetValueUnsafe();
 | 
						|
 | 
						|
  if (pref->GetType() != impl_value->type()) {
 | 
						|
    error = base::StringPrintf(
 | 
						|
        "Trying to set a preference of type %s to value of type %s",
 | 
						|
        GetTypeString(pref->GetType()), GetTypeString(impl_value->type()));
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // PrefService will make a DeepCopy of |impl_value|.
 | 
						|
  pref_service->Set(name, *impl_value);
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ClearCertificateExceptions(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback) {
 | 
						|
  GetBrowserContext(
 | 
						|
      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
 | 
						|
      base::Bind(&CefRequestContextImpl::ClearCertificateExceptionsInternal,
 | 
						|
                 this, callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ClearHttpAuthCredentials(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback) {
 | 
						|
  GetBrowserContext(
 | 
						|
      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
 | 
						|
      base::Bind(&CefRequestContextImpl::ClearHttpAuthCredentialsInternal, this,
 | 
						|
                 callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::CloseAllConnections(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback) {
 | 
						|
  GetBrowserContext(
 | 
						|
      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
 | 
						|
      base::Bind(&CefRequestContextImpl::CloseAllConnectionsInternal, this,
 | 
						|
                 callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ResolveHost(
 | 
						|
    const CefString& origin,
 | 
						|
    CefRefPtr<CefResolveCallback> callback) {
 | 
						|
  GetBrowserContext(base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
 | 
						|
                    base::Bind(&CefRequestContextImpl::ResolveHostInternal,
 | 
						|
                               this, origin, callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::LoadExtension(
 | 
						|
    const CefString& root_directory,
 | 
						|
    CefRefPtr<CefDictionaryValue> manifest,
 | 
						|
    CefRefPtr<CefExtensionHandler> handler) {
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    CEF_POST_TASK(CEF_UIT,
 | 
						|
                  base::BindOnce(&CefRequestContextImpl::LoadExtension, this,
 | 
						|
                                 root_directory, manifest, handler));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!extensions::ExtensionsEnabled()) {
 | 
						|
    if (handler)
 | 
						|
      handler->OnExtensionLoadFailed(ERR_ABORTED);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (manifest && manifest->GetSize() > 0) {
 | 
						|
    CefDictionaryValueImpl* value_impl =
 | 
						|
        static_cast<CefDictionaryValueImpl*>(manifest.get());
 | 
						|
    GetBrowserContext()->extension_system()->LoadExtension(
 | 
						|
        base::WrapUnique(value_impl->CopyValue()), root_directory,
 | 
						|
        false /* builtin */, this, handler);
 | 
						|
  } else {
 | 
						|
    GetBrowserContext()->extension_system()->LoadExtension(
 | 
						|
        root_directory, false /* builtin */, this, handler);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::DidLoadExtension(const CefString& extension_id) {
 | 
						|
  CefRefPtr<CefExtension> extension = GetExtension(extension_id);
 | 
						|
  // GetLoaderContext() will return NULL for internal extensions.
 | 
						|
  return extension && IsSame(extension->GetLoaderContext());
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::HasExtension(const CefString& extension_id) {
 | 
						|
  return !!GetExtension(extension_id);
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::GetExtensions(
 | 
						|
    std::vector<CefString>& extension_ids) {
 | 
						|
  extension_ids.clear();
 | 
						|
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!extensions::ExtensionsEnabled())
 | 
						|
    return false;
 | 
						|
 | 
						|
  extensions::CefExtensionSystem::ExtensionMap extension_map =
 | 
						|
      GetBrowserContext()->extension_system()->GetExtensions();
 | 
						|
  extensions::CefExtensionSystem::ExtensionMap::const_iterator it =
 | 
						|
      extension_map.begin();
 | 
						|
  for (; it != extension_map.end(); ++it)
 | 
						|
    extension_ids.push_back(it->second->GetIdentifier());
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
CefRefPtr<CefExtension> CefRequestContextImpl::GetExtension(
 | 
						|
    const CefString& extension_id) {
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!extensions::ExtensionsEnabled())
 | 
						|
    return nullptr;
 | 
						|
 | 
						|
  return GetBrowserContext()->extension_system()->GetExtension(extension_id);
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::OnRenderFrameCreated(int render_process_id,
 | 
						|
                                                 int render_frame_id,
 | 
						|
                                                 int frame_tree_node_id,
 | 
						|
                                                 bool is_main_frame,
 | 
						|
                                                 bool is_guest_view) {
 | 
						|
  browser_context_->OnRenderFrameCreated(this, render_process_id,
 | 
						|
                                         render_frame_id, frame_tree_node_id,
 | 
						|
                                         is_main_frame, is_guest_view);
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::OnRenderFrameDeleted(int render_process_id,
 | 
						|
                                                 int render_frame_id,
 | 
						|
                                                 int frame_tree_node_id,
 | 
						|
                                                 bool is_main_frame,
 | 
						|
                                                 bool is_guest_view) {
 | 
						|
  browser_context_->OnRenderFrameDeleted(this, render_process_id,
 | 
						|
                                         render_frame_id, frame_tree_node_id,
 | 
						|
                                         is_main_frame, is_guest_view);
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
CefRefPtr<CefRequestContextImpl>
 | 
						|
CefRequestContextImpl::GetOrCreateRequestContext(const Config& config) {
 | 
						|
  if (config.is_global ||
 | 
						|
      (config.other && config.other->IsGlobal() && !config.handler)) {
 | 
						|
    // Return the singleton global context.
 | 
						|
    return CefContentBrowserClient::Get()->request_context();
 | 
						|
  }
 | 
						|
 | 
						|
  // The new context will be initialized later by EnsureBrowserContext().
 | 
						|
  return new CefRequestContextImpl(config);
 | 
						|
}
 | 
						|
 | 
						|
CefRequestContextImpl::CefRequestContextImpl(
 | 
						|
    const CefRequestContextImpl::Config& config)
 | 
						|
    : config_(config) {}
 | 
						|
 | 
						|
void CefRequestContextImpl::Initialize() {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  DCHECK(!browser_context_);
 | 
						|
 | 
						|
  if (config_.other) {
 | 
						|
    // Share storage with |config_.other|.
 | 
						|
    browser_context_ =
 | 
						|
        CefBrowserContext::GetForContext(config_.other->GetBrowserContext());
 | 
						|
  }
 | 
						|
 | 
						|
  if (!browser_context_) {
 | 
						|
    const base::FilePath& cache_path =
 | 
						|
        base::FilePath(CefString(&config_.settings.cache_path));
 | 
						|
    if (!cache_path.empty()) {
 | 
						|
      // Check if a CefBrowserContext is already globally registered for
 | 
						|
      // the specified cache path. If so then use it.
 | 
						|
      browser_context_ = CefBrowserContext::GetForCachePath(cache_path);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!browser_context_) {
 | 
						|
    // Create a new CefBrowserContext instance. If the cache path is non-
 | 
						|
    // empty then this new instance will become the globally registered
 | 
						|
    // CefBrowserContext for that path. Otherwise, this new instance will
 | 
						|
    // be a completely isolated "incongento mode" context.
 | 
						|
    browser_context_ = new CefBrowserContext(config_.settings);
 | 
						|
    browser_context_->Initialize();
 | 
						|
  }
 | 
						|
 | 
						|
  // We'll disassociate from |browser_context_| on destruction.
 | 
						|
  browser_context_->AddCefRequestContext(this);
 | 
						|
 | 
						|
  // Force our settings to match |browser_context_|.
 | 
						|
  config_.settings = browser_context_->GetSettings();
 | 
						|
 | 
						|
  if (config_.other) {
 | 
						|
    // Clear the reference to |config_.other| after setting
 | 
						|
    // |request_context_getter_|. This is the reverse order of checks in
 | 
						|
    // IsSharedWith().
 | 
						|
    config_.other = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (config_.handler)
 | 
						|
    config_.handler->OnRequestContextInitialized(this);
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::EnsureBrowserContext() {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  if (!browser_context())
 | 
						|
    Initialize();
 | 
						|
  DCHECK(browser_context());
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::GetBrowserContextOnUIThread(
 | 
						|
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
 | 
						|
    const BrowserContextCallback& callback) {
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_UIT, base::Bind(&CefRequestContextImpl::GetBrowserContextOnUIThread,
 | 
						|
                            this, task_runner, callback));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the browser context exists.
 | 
						|
  EnsureBrowserContext();
 | 
						|
 | 
						|
  if (task_runner->BelongsToCurrentThread()) {
 | 
						|
    // Execute the callback immediately.
 | 
						|
    callback.Run(browser_context());
 | 
						|
  } else {
 | 
						|
    // Execute the callback on the target thread.
 | 
						|
    task_runner->PostTask(FROM_HERE, base::Bind(callback, browser_context()));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::PurgePluginListCacheInternal(
 | 
						|
    bool reload_pages,
 | 
						|
    CefBrowserContext* browser_context) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  browser_context->ClearPluginLoadDecision(-1);
 | 
						|
  content::PluginService::GetInstance()->PurgePluginListCache(browser_context,
 | 
						|
                                                              false);
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ClearCertificateExceptionsInternal(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback,
 | 
						|
    CefBrowserContext* browser_context) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  content::SSLHostStateDelegate* ssl_delegate =
 | 
						|
      browser_context->GetSSLHostStateDelegate();
 | 
						|
  if (ssl_delegate)
 | 
						|
    ssl_delegate->Clear(base::Callback<bool(const std::string&)>());
 | 
						|
 | 
						|
  if (callback) {
 | 
						|
    CEF_POST_TASK(CEF_UIT,
 | 
						|
                  base::Bind(&CefCompletionCallback::OnComplete, callback));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ClearHttpAuthCredentialsInternal(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback,
 | 
						|
    CefBrowserContext* browser_context) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  browser_context->GetNetworkContext()->ClearHttpAuthCache(
 | 
						|
      base::Time(), base::Bind(&CefCompletionCallback::OnComplete, callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::CloseAllConnectionsInternal(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback,
 | 
						|
    CefBrowserContext* browser_context) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  browser_context->GetNetworkContext()->CloseAllConnections(
 | 
						|
      base::Bind(&CefCompletionCallback::OnComplete, callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ResolveHostInternal(
 | 
						|
    const CefString& origin,
 | 
						|
    CefRefPtr<CefResolveCallback> callback,
 | 
						|
    CefBrowserContext* browser_context) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  // |helper| will be deleted in ResolveHostHelper::OnComplete().
 | 
						|
  ResolveHostHelper* helper = new ResolveHostHelper(callback);
 | 
						|
  helper->Start(browser_context, origin);
 | 
						|
}
 | 
						|
 | 
						|
CefBrowserContext* CefRequestContextImpl::browser_context() const {
 | 
						|
  return browser_context_;
 | 
						|
}
 |