mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	- Configuration of OSR VSync interval is currently missing (issue #2517) - Rename VERSION to VERSION.in to fix libc++ compile error (issue #2518)
		
			
				
	
	
		
			825 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			825 lines
		
	
	
		
			26 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_impl.h"
 | 
						|
#include "libcef/browser/browser_context_proxy.h"
 | 
						|
#include "libcef/browser/content_browser_client.h"
 | 
						|
#include "libcef/browser/context.h"
 | 
						|
#include "libcef/browser/cookie_manager_impl.h"
 | 
						|
#include "libcef/browser/extensions/extension_system.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 "net/http/http_cache.h"
 | 
						|
#include "net/http/http_transaction_factory.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";
 | 
						|
  }
 | 
						|
 | 
						|
  NOTREACHED();
 | 
						|
  return "UNKNOWN";
 | 
						|
}
 | 
						|
 | 
						|
// Helper for HostResolver::Resolve.
 | 
						|
struct ResolveHostHelper {
 | 
						|
  explicit ResolveHostHelper(CefRefPtr<CefResolveCallback> callback)
 | 
						|
      : callback_(callback) {}
 | 
						|
 | 
						|
  void OnResolveCompleted(int result) {
 | 
						|
    std::vector<CefString> resolved_ips;
 | 
						|
 | 
						|
    net::AddressList::const_iterator iter = address_list_.begin();
 | 
						|
    for (; iter != 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_;
 | 
						|
  net::AddressList address_list_;
 | 
						|
  std::unique_ptr<net::HostResolver::Request> request_;
 | 
						|
};
 | 
						|
 | 
						|
}  // 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();
 | 
						|
 | 
						|
  // Delete the proxy first because it also references |browser_context_impl_|.
 | 
						|
  if (browser_context_proxy_)
 | 
						|
    browser_context_proxy_.reset(nullptr);
 | 
						|
 | 
						|
  if (browser_context_impl_) {
 | 
						|
    // May result in |browser_context_impl_| being deleted if no other
 | 
						|
    // CefRequestContextImpl are referencing it.
 | 
						|
    browser_context_impl_->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);
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::GetRequestContextImpl(
 | 
						|
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
 | 
						|
    const RequestContextCallback& callback) {
 | 
						|
  if (!task_runner.get())
 | 
						|
    task_runner = CefTaskRunnerImpl::GetCurrentTaskRunner();
 | 
						|
  if (request_context_getter_impl_) {
 | 
						|
    // The browser context already exists.
 | 
						|
    DCHECK(browser_context());
 | 
						|
    GetRequestContextImplOnIOThread(task_runner, callback, browser_context());
 | 
						|
  } else {
 | 
						|
    // Need to initialize the browser context first.
 | 
						|
    GetBrowserContextOnUIThread(
 | 
						|
        base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
 | 
						|
        base::Bind(&CefRequestContextImpl::GetRequestContextImplOnIOThread,
 | 
						|
                   this, 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()) {
 | 
						|
    if (browser_context()->is_proxy() &&
 | 
						|
        other_impl->browser_context()->is_proxy()) {
 | 
						|
      CefBrowserContextProxy* proxy =
 | 
						|
          static_cast<CefBrowserContextProxy*>(browser_context());
 | 
						|
      CefBrowserContextProxy* other_proxy =
 | 
						|
          static_cast<CefBrowserContextProxy*>(other_impl->browser_context());
 | 
						|
      return (proxy->parent() == other_proxy->parent() &&
 | 
						|
              proxy->GetHandler() == other_proxy->GetHandler());
 | 
						|
    }
 | 
						|
    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);
 | 
						|
  }
 | 
						|
 | 
						|
  if (request_context_getter_impl_ &&
 | 
						|
      other_impl->request_context_getter_impl_) {
 | 
						|
    // Both objects are initialized. Compare the request context objects.
 | 
						|
    return (request_context_getter_impl_ ==
 | 
						|
            other_impl->request_context_getter_impl_);
 | 
						|
  }
 | 
						|
 | 
						|
  // 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::GetDefaultCookieManager(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback) {
 | 
						|
  CefRefPtr<CefCookieManagerImpl> cookie_manager =
 | 
						|
      new CefCookieManagerImpl(false);
 | 
						|
  cookie_manager->Initialize(this, CefString(), false, callback);
 | 
						|
  return cookie_manager.get();
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::RegisterSchemeHandlerFactory(
 | 
						|
    const CefString& scheme_name,
 | 
						|
    const CefString& domain_name,
 | 
						|
    CefRefPtr<CefSchemeHandlerFactory> factory) {
 | 
						|
  GetRequestContextImpl(
 | 
						|
      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
 | 
						|
      base::Bind(&CefRequestContextImpl::RegisterSchemeHandlerFactoryInternal,
 | 
						|
                 this, scheme_name, domain_name, factory));
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool CefRequestContextImpl::ClearSchemeHandlerFactories() {
 | 
						|
  GetRequestContextImpl(
 | 
						|
      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
 | 
						|
      base::Bind(&CefRequestContextImpl::ClearSchemeHandlerFactoriesInternal,
 | 
						|
                 this));
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::PurgePluginListCache(bool reload_pages) {
 | 
						|
  GetBrowserContext(
 | 
						|
      base::CreateSingleThreadTaskRunnerWithTraits({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::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
 | 
						|
      base::Bind(&CefRequestContextImpl::ClearCertificateExceptionsInternal,
 | 
						|
                 this, callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::CloseAllConnections(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback) {
 | 
						|
  GetRequestContextImpl(
 | 
						|
      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
 | 
						|
      base::Bind(&CefRequestContextImpl::CloseAllConnectionsInternal, this,
 | 
						|
                 callback));
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ResolveHost(
 | 
						|
    const CefString& origin,
 | 
						|
    CefRefPtr<CefResolveCallback> callback) {
 | 
						|
  GetRequestContextImpl(
 | 
						|
      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
 | 
						|
      base::Bind(&CefRequestContextImpl::ResolveHostInternal, this, origin,
 | 
						|
                 callback));
 | 
						|
}
 | 
						|
 | 
						|
cef_errorcode_t CefRequestContextImpl::ResolveHostCached(
 | 
						|
    const CefString& origin,
 | 
						|
    std::vector<CefString>& resolved_ips) {
 | 
						|
  resolved_ips.clear();
 | 
						|
 | 
						|
  if (!CEF_CURRENTLY_ON_IOT()) {
 | 
						|
    NOTREACHED() << "called on invalid thread";
 | 
						|
    return ERR_FAILED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!request_context_getter_impl_)
 | 
						|
    return ERR_FAILED;
 | 
						|
 | 
						|
  int retval = ERR_FAILED;
 | 
						|
 | 
						|
  net::HostResolver* host_resolver =
 | 
						|
      request_context_getter_impl_->GetHostResolver();
 | 
						|
  if (host_resolver) {
 | 
						|
    net::HostResolver::RequestInfo request_info(
 | 
						|
        net::HostPortPair::FromURL(GURL(origin.ToString())));
 | 
						|
    net::AddressList address_list;
 | 
						|
    retval = host_resolver->ResolveFromCache(request_info, &address_list,
 | 
						|
                                             net::NetLogWithSource());
 | 
						|
    if (retval == net::OK) {
 | 
						|
      net::AddressList::const_iterator iter = address_list.begin();
 | 
						|
      for (; iter != address_list.end(); ++iter)
 | 
						|
        resolved_ips.push_back(iter->ToString());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return static_cast<cef_errorcode_t>(retval);
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
// 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_impl_);
 | 
						|
  DCHECK(!request_context_getter_impl_);
 | 
						|
 | 
						|
  if (config_.other) {
 | 
						|
    // Share storage with |config_.other|.
 | 
						|
    browser_context_impl_ = CefBrowserContextImpl::GetForContext(
 | 
						|
        config_.other->GetBrowserContext());
 | 
						|
  }
 | 
						|
 | 
						|
  if (!browser_context_impl_) {
 | 
						|
    const base::FilePath& cache_path =
 | 
						|
        base::FilePath(CefString(&config_.settings.cache_path));
 | 
						|
    if (!cache_path.empty()) {
 | 
						|
      // Check if a CefBrowserContextImpl is already globally registered for
 | 
						|
      // the specified cache path. If so then use it.
 | 
						|
      browser_context_impl_ =
 | 
						|
          CefBrowserContextImpl::GetForCachePath(cache_path);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!browser_context_impl_) {
 | 
						|
    // Create a new CefBrowserContextImpl instance. If the cache path is non-
 | 
						|
    // empty then this new instance will become the globally registered
 | 
						|
    // CefBrowserContextImpl for that path. Otherwise, this new instance will
 | 
						|
    // be a completely isolated "incongento mode" context.
 | 
						|
    browser_context_impl_ = new CefBrowserContextImpl(config_.settings);
 | 
						|
    browser_context_impl_->Initialize();
 | 
						|
  }
 | 
						|
 | 
						|
  // We'll disassociate from |browser_context_impl_| on destruction.
 | 
						|
  browser_context_impl_->AddCefRequestContext(this);
 | 
						|
 | 
						|
  // Force our settings to match |browser_context_impl_|.
 | 
						|
  config_.settings = browser_context_impl_->GetSettings();
 | 
						|
 | 
						|
  if (config_.handler.get()) {
 | 
						|
    // Use a proxy that will execute handler callbacks where appropriate and
 | 
						|
    // otherwise forward all requests to |browser_context_impl_|.
 | 
						|
    browser_context_proxy_.reset(new CefBrowserContextProxy(
 | 
						|
        this, config_.handler, browser_context_impl_));
 | 
						|
    browser_context_proxy_->Initialize();
 | 
						|
    DCHECK(!config_.is_global);
 | 
						|
  }
 | 
						|
 | 
						|
  request_context_getter_impl_ =
 | 
						|
      browser_context_impl_->request_context_getter().get();
 | 
						|
  DCHECK(request_context_getter_impl_);
 | 
						|
 | 
						|
  if (config_.handler.get()) {
 | 
						|
    // Keep the handler alive until the associated request context is
 | 
						|
    // destroyed.
 | 
						|
    request_context_getter_impl_->AddHandler(config_.handler);
 | 
						|
  }
 | 
						|
 | 
						|
  if (config_.other) {
 | 
						|
    // Clear the reference to |config_.other| after setting
 | 
						|
    // |request_context_getter_impl_|. 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());
 | 
						|
  DCHECK(request_context_getter_impl_);
 | 
						|
}
 | 
						|
 | 
						|
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::GetRequestContextImplOnIOThread(
 | 
						|
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
 | 
						|
    const RequestContextCallback& callback,
 | 
						|
    CefBrowserContext* browser_context) {
 | 
						|
  if (!CEF_CURRENTLY_ON_IOT()) {
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_IOT,
 | 
						|
        base::Bind(&CefRequestContextImpl::GetRequestContextImplOnIOThread,
 | 
						|
                   this, task_runner, callback, browser_context));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  DCHECK(request_context_getter_impl_);
 | 
						|
 | 
						|
  // Make sure the request context exists.
 | 
						|
  request_context_getter_impl_->GetURLRequestContext();
 | 
						|
 | 
						|
  if (task_runner->BelongsToCurrentThread()) {
 | 
						|
    // Execute the callback immediately.
 | 
						|
    callback.Run(request_context_getter_impl_);
 | 
						|
  } else {
 | 
						|
    // Execute the callback on the target thread.
 | 
						|
    task_runner->PostTask(
 | 
						|
        FROM_HERE, base::Bind(callback, base::WrapRefCounted(
 | 
						|
                                            request_context_getter_impl_)));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::RegisterSchemeHandlerFactoryInternal(
 | 
						|
    const CefString& scheme_name,
 | 
						|
    const CefString& domain_name,
 | 
						|
    CefRefPtr<CefSchemeHandlerFactory> factory,
 | 
						|
    scoped_refptr<CefURLRequestContextGetterImpl> request_context) {
 | 
						|
  CEF_REQUIRE_IOT();
 | 
						|
  request_context->request_manager()->AddFactory(scheme_name, domain_name,
 | 
						|
                                                 factory);
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ClearSchemeHandlerFactoriesInternal(
 | 
						|
    scoped_refptr<CefURLRequestContextGetterImpl> request_context) {
 | 
						|
  CEF_REQUIRE_IOT();
 | 
						|
  request_context->request_manager()->ClearFactories();
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::PurgePluginListCacheInternal(
 | 
						|
    bool reload_pages,
 | 
						|
    CefBrowserContext* browser_context) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  browser_context->OnPurgePluginListCache();
 | 
						|
  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::CloseAllConnectionsInternal(
 | 
						|
    CefRefPtr<CefCompletionCallback> callback,
 | 
						|
    scoped_refptr<CefURLRequestContextGetterImpl> request_context) {
 | 
						|
  CEF_REQUIRE_IOT();
 | 
						|
 | 
						|
  net::URLRequestContext* url_context = request_context->GetURLRequestContext();
 | 
						|
  if (url_context) {
 | 
						|
    net::HttpTransactionFactory* http_factory =
 | 
						|
        url_context->http_transaction_factory();
 | 
						|
    if (http_factory) {
 | 
						|
      net::HttpCache* cache = http_factory->GetCache();
 | 
						|
      if (cache)
 | 
						|
        cache->CloseAllConnections();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (callback) {
 | 
						|
    CEF_POST_TASK(CEF_UIT,
 | 
						|
                  base::Bind(&CefCompletionCallback::OnComplete, callback));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void CefRequestContextImpl::ResolveHostInternal(
 | 
						|
    const CefString& origin,
 | 
						|
    CefRefPtr<CefResolveCallback> callback,
 | 
						|
    scoped_refptr<CefURLRequestContextGetterImpl> request_context) {
 | 
						|
  CEF_REQUIRE_IOT();
 | 
						|
 | 
						|
  int retval = ERR_FAILED;
 | 
						|
 | 
						|
  // |helper| will be deleted in ResolveHostHelper::OnResolveCompleted().
 | 
						|
  ResolveHostHelper* helper = new ResolveHostHelper(callback);
 | 
						|
 | 
						|
  net::HostResolver* host_resolver = request_context->GetHostResolver();
 | 
						|
  if (host_resolver) {
 | 
						|
    net::HostResolver::RequestInfo request_info(
 | 
						|
        net::HostPortPair::FromURL(GURL(origin.ToString())));
 | 
						|
    retval = host_resolver->Resolve(
 | 
						|
        request_info, net::DEFAULT_PRIORITY, &helper->address_list_,
 | 
						|
        base::Bind(&ResolveHostHelper::OnResolveCompleted,
 | 
						|
                   base::Unretained(helper)),
 | 
						|
        &helper->request_, net::NetLogWithSource());
 | 
						|
    if (retval == net::ERR_IO_PENDING) {
 | 
						|
      // The result will be delivered asynchronously via the callback.
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  helper->OnResolveCompleted(retval);
 | 
						|
}
 | 
						|
 | 
						|
CefBrowserContext* CefRequestContextImpl::browser_context() const {
 | 
						|
  if (browser_context_proxy_)
 | 
						|
    return browser_context_proxy_.get();
 | 
						|
  return browser_context_impl_;
 | 
						|
}
 |