// Copyright (c) 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "libcef/browser/resource_context.h" #include "libcef/browser/net/scheme_handler.h" #include "libcef/browser/thread_util.h" #include "libcef/common/net/scheme_registration.h" #include "base/i18n/case_conversion.h" #include "base/logging.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/resource_context_impl.h" #include "content/public/browser/browser_thread.h" #if defined(USE_NSS_CERTS) #include "net/ssl/client_cert_store_nss.h" #endif #if defined(OS_WIN) #include "net/ssl/client_cert_store_win.h" #endif #if defined(OS_MACOSX) #include "net/ssl/client_cert_store_mac.h" #endif CefResourceContext::CefResourceContext(bool is_off_the_record) : is_off_the_record_(is_off_the_record) { // Using base::Unretained() is safe because both this callback and possible // deletion of |this| will execute on the IO thread, and this callback will // be executed first. CEF_POST_TASK(CEF_IOT, base::Bind(&CefResourceContext::InitOnIOThread, base::Unretained(this))); } CefResourceContext::~CefResourceContext() {} std::unique_ptr CefResourceContext::CreateClientCertStore() { #if defined(USE_NSS_CERTS) return std::unique_ptr(new net::ClientCertStoreNSS( net::ClientCertStoreNSS::PasswordDelegateFactory())); #elif defined(OS_WIN) return std::unique_ptr(new net::ClientCertStoreWin()); #elif defined(OS_MACOSX) return std::unique_ptr(new net::ClientCertStoreMac()); #elif defined(USE_OPENSSL) // OpenSSL does not use the ClientCertStore infrastructure. On Android client // cert matching is done by the OS as part of the call to show the cert // selection dialog. return std::unique_ptr(); #else #error Unknown platform. #endif } void CefResourceContext::AddHandler( int render_process_id, int render_frame_id, int frame_tree_node_id, CefRefPtr handler) { CEF_REQUIRE_IOT(); handler_map_.AddHandler(render_process_id, render_frame_id, frame_tree_node_id, handler); } void CefResourceContext::RemoveHandler(int render_process_id, int render_frame_id, int frame_tree_node_id) { CEF_REQUIRE_IOT(); handler_map_.RemoveHandler(render_process_id, render_frame_id, frame_tree_node_id); } CefRefPtr CefResourceContext::GetHandler( int render_process_id, int render_frame_id, int frame_tree_node_id, bool require_frame_match) const { CEF_REQUIRE_IOT(); return handler_map_.GetHandler(render_process_id, render_frame_id, frame_tree_node_id, require_frame_match); } void CefResourceContext::RegisterSchemeHandlerFactory( const std::string& scheme_name, const std::string& domain_name, CefRefPtr factory) { CEF_REQUIRE_IOT(); const std::string& scheme_lower = base::ToLowerASCII(scheme_name); std::string domain_lower; // Hostname is only supported for standard schemes. if (scheme::IsStandardScheme(scheme_lower)) { // Hostname might contain Unicode characters. domain_lower = base::UTF16ToUTF8(base::i18n::ToLower(base::UTF8ToUTF16(domain_name))); } const auto key = std::make_pair(scheme_lower, domain_lower); if (factory) { // Add or replace the factory. scheme_handler_factory_map_[key] = factory; } else { // Remove the existing factory, if any. auto it = scheme_handler_factory_map_.find(key); if (it != scheme_handler_factory_map_.end()) scheme_handler_factory_map_.erase(it); } } void CefResourceContext::ClearSchemeHandlerFactories() { CEF_REQUIRE_IOT(); scheme_handler_factory_map_.clear(); // Restore the default internal handlers. scheme::RegisterInternalHandlers(this); } CefRefPtr CefResourceContext::GetSchemeHandlerFactory( const GURL& url) { CEF_REQUIRE_IOT(); if (scheme_handler_factory_map_.empty()) return nullptr; const std::string& scheme_lower = url.scheme(); const std::string& domain_lower = url.IsStandard() ? url.host() : std::string(); if (!domain_lower.empty()) { // Sanity check. DCHECK(scheme::IsStandardScheme(scheme_lower)) << scheme_lower; // Try for a match with hostname first. const auto it = scheme_handler_factory_map_.find( std::make_pair(scheme_lower, domain_lower)); if (it != scheme_handler_factory_map_.end()) return it->second; } // Try for a match with no specified hostname. const auto it = scheme_handler_factory_map_.find( std::make_pair(scheme_lower, std::string())); if (it != scheme_handler_factory_map_.end()) return it->second; return nullptr; } void CefResourceContext::InitOnIOThread() { CEF_REQUIRE_IOT(); // Add the default internal handlers. scheme::RegisterInternalHandlers(this); }