| // Copyright (c) 2012 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/browser_context.h" |
| |
| #include <map> |
| #include <utility> |
| |
| #include "libcef/browser/content_browser_client.h" |
| #include "libcef/browser/download_manager_delegate.h" |
| #include "libcef/browser/extensions/extension_system.h" |
| #include "libcef/browser/media_router/media_router_manager.h" |
| #include "libcef/browser/prefs/browser_prefs.h" |
| #include "libcef/browser/request_context_impl.h" |
| #include "libcef/browser/ssl_host_state_delegate.h" |
| #include "libcef/browser/thread_util.h" |
| #include "libcef/common/cef_switches.h" |
| #include "libcef/common/extensions/extensions_util.h" |
| |
| #include "base/command_line.h" |
| #include "base/files/file_util.h" |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/strings/string_util.h" |
| #include "chrome/browser/font_family_cache.h" |
| #include "chrome/browser/plugins/chrome_plugin_service_filter.h" |
| #include "chrome/browser/profiles/profile_key.h" |
| #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h" |
| #include "chrome/common/pref_names.h" |
| #include "components/content_settings/core/browser/host_content_settings_map.h" |
| #include "components/guest_view/browser/guest_view_manager.h" |
| #include "components/keyed_service/content/browser_context_dependency_manager.h" |
| #include "components/keyed_service/core/simple_dependency_manager.h" |
| #include "components/keyed_service/core/simple_key_map.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/proxy_config/pref_proxy_config_tracker_impl.h" |
| #include "components/user_prefs/user_prefs.h" |
| #include "components/visitedlink/browser/visitedlink_event_listener.h" |
| #include "components/visitedlink/browser/visitedlink_writer.h" |
| #include "components/zoom/zoom_event_manager.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/download_manager.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "extensions/browser/extension_protocols.h" |
| #include "extensions/browser/process_manager.h" |
| #include "extensions/common/constants.h" |
| #include "net/proxy_resolution/proxy_config_service.h" |
| #include "services/network/public/mojom/cors_origin_pattern.mojom.h" |
| |
| using content::BrowserThread; |
| |
| namespace { |
| |
| // Manages the global list of Impl instances. |
| class ImplManager { |
| public: |
| typedef std::vector<CefBrowserContext*> Vector; |
| |
| ImplManager() {} |
| ~ImplManager() { |
| DCHECK(all_.empty()); |
| DCHECK(map_.empty()); |
| } |
| |
| void AddImpl(CefBrowserContext* impl) { |
| CEF_REQUIRE_UIT(); |
| DCHECK(!IsValidImpl(impl)); |
| all_.push_back(impl); |
| } |
| |
| void RemoveImpl(CefBrowserContext* impl, const base::FilePath& path) { |
| CEF_REQUIRE_UIT(); |
| |
| Vector::iterator it = GetImplPos(impl); |
| DCHECK(it != all_.end()); |
| all_.erase(it); |
| |
| if (!path.empty()) { |
| PathMap::iterator it = map_.find(path); |
| DCHECK(it != map_.end()); |
| if (it != map_.end()) |
| map_.erase(it); |
| } |
| } |
| |
| bool IsValidImpl(const CefBrowserContext* impl) { |
| CEF_REQUIRE_UIT(); |
| return GetImplPos(impl) != all_.end(); |
| } |
| |
| CefBrowserContext* GetImplForIDs(int render_process_id, |
| int render_frame_id, |
| int frame_tree_node_id, |
| bool require_frame_match) { |
| CEF_REQUIRE_UIT(); |
| for (const auto& context : all_) { |
| if (context->IsAssociatedContext(render_process_id, render_frame_id, |
| frame_tree_node_id, |
| require_frame_match)) { |
| return context; |
| } |
| } |
| return nullptr; |
| } |
| |
| CefBrowserContext* GetImplForContext(const content::BrowserContext* context) { |
| CEF_REQUIRE_UIT(); |
| if (!context) |
| return nullptr; |
| |
| Vector::iterator it = all_.begin(); |
| for (; it != all_.end(); ++it) { |
| if (*it == context) |
| return *it; |
| } |
| return nullptr; |
| } |
| |
| void SetImplPath(CefBrowserContext* impl, const base::FilePath& path) { |
| CEF_REQUIRE_UIT(); |
| DCHECK(!path.empty()); |
| DCHECK(IsValidImpl(impl)); |
| DCHECK(GetImplForPath(path) == nullptr); |
| map_.insert(std::make_pair(path, impl)); |
| } |
| |
| CefBrowserContext* GetImplForPath(const base::FilePath& path) { |
| CEF_REQUIRE_UIT(); |
| DCHECK(!path.empty()); |
| PathMap::const_iterator it = map_.find(path); |
| if (it != map_.end()) |
| return it->second; |
| return nullptr; |
| } |
| |
| const Vector GetAllImpl() const { return all_; } |
| |
| private: |
| Vector::iterator GetImplPos(const CefBrowserContext* impl) { |
| Vector::iterator it = all_.begin(); |
| for (; it != all_.end(); ++it) { |
| if (*it == impl) |
| return it; |
| } |
| return all_.end(); |
| } |
| |
| typedef std::map<base::FilePath, CefBrowserContext*> PathMap; |
| PathMap map_; |
| |
| Vector all_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ImplManager); |
| }; |
| |
| #if DCHECK_IS_ON() |
| // Because of DCHECK()s in the object destructor. |
| base::LazyInstance<ImplManager>::DestructorAtExit g_manager = |
| LAZY_INSTANCE_INITIALIZER; |
| #else |
| base::LazyInstance<ImplManager>::Leaky g_manager = LAZY_INSTANCE_INITIALIZER; |
| #endif |
| |
| CefBrowserContext* GetSelf(base::WeakPtr<CefBrowserContext> self) { |
| CEF_REQUIRE_UIT(); |
| return self.get(); |
| } |
| |
| } // namespace |
| |
| // Creates and manages VisitedLinkEventListener objects for each |
| // CefBrowserContext sharing the same VisitedLinkWriter. |
| class CefVisitedLinkListener : public visitedlink::VisitedLinkWriter::Listener { |
| public: |
| CefVisitedLinkListener() { DCHECK(listener_map_.empty()); } |
| |
| void CreateListenerForContext(const CefBrowserContext* context) { |
| CEF_REQUIRE_UIT(); |
| auto listener = std::make_unique<visitedlink::VisitedLinkEventListener>( |
| const_cast<CefBrowserContext*>(context)); |
| listener_map_.insert(std::make_pair(context, std::move(listener))); |
| } |
| |
| void RemoveListenerForContext(const CefBrowserContext* context) { |
| CEF_REQUIRE_UIT(); |
| ListenerMap::iterator it = listener_map_.find(context); |
| DCHECK(it != listener_map_.end()); |
| listener_map_.erase(it); |
| } |
| |
| // visitedlink::VisitedLinkWriter::Listener methods. |
| |
| void NewTable(base::ReadOnlySharedMemoryRegion* table_region) override { |
| CEF_REQUIRE_UIT(); |
| ListenerMap::iterator it = listener_map_.begin(); |
| for (; it != listener_map_.end(); ++it) |
| it->second->NewTable(table_region); |
| } |
| |
| void Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint) override { |
| CEF_REQUIRE_UIT(); |
| ListenerMap::iterator it = listener_map_.begin(); |
| for (; it != listener_map_.end(); ++it) |
| it->second->Add(fingerprint); |
| } |
| |
| void Reset(bool invalidate_hashes) override { |
| CEF_REQUIRE_UIT(); |
| ListenerMap::iterator it = listener_map_.begin(); |
| for (; it != listener_map_.end(); ++it) |
| it->second->Reset(invalidate_hashes); |
| } |
| |
| private: |
| // Map of CefBrowserContext to the associated VisitedLinkEventListener. |
| typedef std::map<const CefBrowserContext*, |
| std::unique_ptr<visitedlink::VisitedLinkEventListener>> |
| ListenerMap; |
| ListenerMap listener_map_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CefVisitedLinkListener); |
| }; |
| |
| CefBrowserContext::CefBrowserContext(const CefRequestContextSettings& settings) |
| : settings_(settings), weak_ptr_factory_(this) { |
| g_manager.Get().AddImpl(this); |
| getter_ = base::BindRepeating(GetSelf, weak_ptr_factory_.GetWeakPtr()); |
| } |
| |
| CefBrowserContext::~CefBrowserContext() { |
| CEF_REQUIRE_UIT(); |
| |
| // No CefRequestContext should be referencing this object any longer. |
| DCHECK(request_context_set_.empty()); |
| |
| // Unregister the context first to avoid re-entrancy during shutdown. |
| g_manager.Get().RemoveImpl(this, cache_path_); |
| |
| // Destroy objects that may hold references to the MediaRouter. |
| media_router_manager_.reset(); |
| |
| // Send notifications to clean up objects associated with this Profile. |
| MaybeSendDestroyedNotification(); |
| |
| ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this); |
| |
| // Remove any BrowserContextKeyedServiceFactory associations. This must be |
| // called before the ProxyService owned by CefBrowserContext is destroyed. |
| // The SimpleDependencyManager should always be passed after the |
| // BrowserContextDependencyManager. This is because the KeyedService instances |
| // in the BrowserContextDependencyManager's dependency graph can depend on the |
| // ones in the SimpleDependencyManager's graph. |
| DependencyManager::PerformInterlockedTwoPhaseShutdown( |
| BrowserContextDependencyManager::GetInstance(), this, |
| SimpleDependencyManager::GetInstance(), key_.get()); |
| |
| key_.reset(); |
| SimpleKeyMap::GetInstance()->Dissociate(this); |
| |
| // Shuts down the storage partitions associated with this browser context. |
| // This must be called before the browser context is actually destroyed |
| // and before a clean-up task for its corresponding IO thread residents |
| // (e.g. ResourceContext) is posted, so that the classes that hung on |
| // StoragePartition can have time to do necessary cleanups on IO thread. |
| ShutdownStoragePartitions(); |
| |
| if (resource_context_.get()) { |
| // Destruction of the ResourceContext will trigger destruction of all |
| // associated network requests. |
| content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, |
| resource_context_.release()); |
| } |
| |
| visitedlink_listener_->RemoveListenerForContext(this); |
| |
| // The FontFamilyCache references the ProxyService so delete it before the |
| // ProxyService is deleted. |
| SetUserData(&kFontFamilyCacheKey, nullptr); |
| |
| pref_proxy_config_tracker_->DetachFromPrefService(); |
| |
| if (host_content_settings_map_) |
| host_content_settings_map_->ShutdownOnUIThread(); |
| |
| // Delete the download manager delegate here because otherwise we'll crash |
| // when it's accessed from the content::BrowserContext destructor. |
| if (download_manager_delegate_) |
| download_manager_delegate_.reset(nullptr); |
| } |
| |
| void CefBrowserContext::Initialize() { |
| cache_path_ = base::FilePath(CefString(&settings_.cache_path)); |
| |
| if (!cache_path_.empty()) |
| g_manager.Get().SetImplPath(this, cache_path_); |
| |
| if (!!settings_.persist_session_cookies) { |
| set_should_persist_session_cookies(true); |
| } |
| |
| key_ = std::make_unique<ProfileKey>(cache_path_); |
| SimpleKeyMap::GetInstance()->Associate(this, key_.get()); |
| |
| // Initialize the PrefService object. |
| pref_service_ = browser_prefs::CreatePrefService( |
| this, cache_path_, !!settings_.persist_user_preferences); |
| |
| content::BrowserContext::Initialize(this, cache_path_); |
| |
| resource_context_.reset(new CefResourceContext(IsOffTheRecord())); |
| |
| // This must be called before creating any services to avoid hitting |
| // DependencyManager::AssertContextWasntDestroyed when creating/destroying |
| // multiple browser contexts (due to pointer address reuse). |
| BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices( |
| this); |
| |
| const bool extensions_enabled = extensions::ExtensionsEnabled(); |
| if (extensions_enabled) { |
| // Create the custom ExtensionSystem first because other KeyedServices |
| // depend on it. |
| extension_system_ = static_cast<extensions::CefExtensionSystem*>( |
| extensions::ExtensionSystem::Get(this)); |
| extension_system_->InitForRegularProfile(true); |
| |
| // Make sure the ProcessManager is created so that it receives extension |
| // load notifications. This is necessary for the proper initialization of |
| // background/event pages. |
| extensions::ProcessManager::Get(this); |
| } |
| |
| // Initialize visited links management. |
| base::FilePath visited_link_path; |
| if (!cache_path_.empty()) |
| visited_link_path = cache_path_.Append(FILE_PATH_LITERAL("Visited Links")); |
| visitedlink_listener_ = new CefVisitedLinkListener; |
| visitedlink_master_.reset(new visitedlink::VisitedLinkWriter( |
| visitedlink_listener_, this, !visited_link_path.empty(), false, |
| visited_link_path, 0)); |
| visitedlink_listener_->CreateListenerForContext(this); |
| visitedlink_master_->Init(); |
| |
| // Initialize proxy configuration tracker. |
| pref_proxy_config_tracker_.reset(new PrefProxyConfigTrackerImpl( |
| GetPrefs(), base::CreateSingleThreadTaskRunner({BrowserThread::IO}))); |
| |
| // Spell checking support and possibly other subsystems retrieve the |
| // PrefService associated with a BrowserContext via UserPrefs::Get(). |
| PrefService* pref_service = GetPrefs(); |
| DCHECK(pref_service); |
| user_prefs::UserPrefs::Set(this, pref_service); |
| key_->SetPrefs(pref_service); |
| |
| if (extensions_enabled) |
| extension_system_->Init(); |
| |
| ChromePluginServiceFilter::GetInstance()->RegisterProfile(this); |
| } |
| |
| void CefBrowserContext::AddCefRequestContext(CefRequestContextImpl* context) { |
| CEF_REQUIRE_UIT(); |
| request_context_set_.insert(context); |
| } |
| |
| void CefBrowserContext::RemoveCefRequestContext( |
| CefRequestContextImpl* context) { |
| CEF_REQUIRE_UIT(); |
| |
| if (extensions::ExtensionsEnabled()) { |
| extension_system()->OnRequestContextDeleted(context); |
| } |
| |
| request_context_set_.erase(context); |
| |
| // Delete ourselves when the reference count reaches zero. |
| if (request_context_set_.empty()) |
| delete this; |
| } |
| |
| // static |
| CefBrowserContext* CefBrowserContext::GetForCachePath( |
| const base::FilePath& cache_path) { |
| return g_manager.Get().GetImplForPath(cache_path); |
| } |
| |
| // static |
| CefBrowserContext* CefBrowserContext::GetForIDs(int render_process_id, |
| int render_frame_id, |
| int frame_tree_node_id, |
| bool require_frame_match) { |
| return g_manager.Get().GetImplForIDs(render_process_id, render_frame_id, |
| frame_tree_node_id, require_frame_match); |
| } |
| |
| // static |
| CefBrowserContext* CefBrowserContext::GetForContext( |
| content::BrowserContext* context) { |
| return g_manager.Get().GetImplForContext(context); |
| } |
| |
| // static |
| std::vector<CefBrowserContext*> CefBrowserContext::GetAll() { |
| return g_manager.Get().GetAllImpl(); |
| } |
| |
| content::ResourceContext* CefBrowserContext::GetResourceContext() { |
| return resource_context_.get(); |
| } |
| |
| content::ClientHintsControllerDelegate* |
| CefBrowserContext::GetClientHintsControllerDelegate() { |
| return nullptr; |
| } |
| |
| void CefBrowserContext::SetCorsOriginAccessListForOrigin( |
| const url::Origin& source_origin, |
| std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns, |
| std::vector<network::mojom::CorsOriginPatternPtr> block_patterns, |
| base::OnceClosure closure) { |
| // This method is called for Extension support. |
| base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(closure)); |
| } |
| |
| ChromeZoomLevelPrefs* CefBrowserContext::GetZoomLevelPrefs() { |
| return static_cast<ChromeZoomLevelPrefs*>( |
| GetStoragePartition(this, nullptr)->GetZoomLevelDelegate()); |
| } |
| |
| scoped_refptr<network::SharedURLLoaderFactory> |
| CefBrowserContext::GetURLLoaderFactory() { |
| return GetDefaultStoragePartition(this) |
| ->GetURLLoaderFactoryForBrowserProcess(); |
| } |
| |
| base::FilePath CefBrowserContext::GetPath() { |
| return cache_path_; |
| } |
| |
| base::FilePath CefBrowserContext::GetPath() const { |
| return cache_path_; |
| } |
| |
| std::unique_ptr<content::ZoomLevelDelegate> |
| CefBrowserContext::CreateZoomLevelDelegate( |
| const base::FilePath& partition_path) { |
| if (cache_path_.empty()) |
| return std::unique_ptr<content::ZoomLevelDelegate>(); |
| |
| return base::WrapUnique(new ChromeZoomLevelPrefs( |
| GetPrefs(), cache_path_, partition_path, |
| zoom::ZoomEventManager::GetForBrowserContext(this)->GetWeakPtr())); |
| } |
| |
| bool CefBrowserContext::IsOffTheRecord() const { |
| // CEF contexts are never flagged as off-the-record. It causes problems |
| // for the extension system. |
| return false; |
| } |
| |
| content::DownloadManagerDelegate* |
| CefBrowserContext::GetDownloadManagerDelegate() { |
| if (!download_manager_delegate_) { |
| content::DownloadManager* manager = |
| BrowserContext::GetDownloadManager(this); |
| download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager)); |
| } |
| return download_manager_delegate_.get(); |
| } |
| |
| content::BrowserPluginGuestManager* CefBrowserContext::GetGuestManager() { |
| DCHECK(extensions::ExtensionsEnabled()); |
| return guest_view::GuestViewManager::FromBrowserContext(this); |
| } |
| |
| storage::SpecialStoragePolicy* CefBrowserContext::GetSpecialStoragePolicy() { |
| return nullptr; |
| } |
| |
| content::PushMessagingService* CefBrowserContext::GetPushMessagingService() { |
| return nullptr; |
| } |
| |
| content::StorageNotificationService* |
| CefBrowserContext::GetStorageNotificationService() { |
| return nullptr; |
| } |
| |
| content::SSLHostStateDelegate* CefBrowserContext::GetSSLHostStateDelegate() { |
| if (!ssl_host_state_delegate_.get()) |
| ssl_host_state_delegate_.reset(new CefSSLHostStateDelegate()); |
| return ssl_host_state_delegate_.get(); |
| } |
| |
| content::PermissionControllerDelegate* |
| CefBrowserContext::GetPermissionControllerDelegate() { |
| return nullptr; |
| } |
| |
| content::BackgroundFetchDelegate* |
| CefBrowserContext::GetBackgroundFetchDelegate() { |
| return nullptr; |
| } |
| |
| content::BackgroundSyncController* |
| CefBrowserContext::GetBackgroundSyncController() { |
| return nullptr; |
| } |
| |
| content::BrowsingDataRemoverDelegate* |
| CefBrowserContext::GetBrowsingDataRemoverDelegate() { |
| return nullptr; |
| } |
| |
| PrefService* CefBrowserContext::GetPrefs() { |
| return pref_service_.get(); |
| } |
| |
| const PrefService* CefBrowserContext::GetPrefs() const { |
| return pref_service_.get(); |
| } |
| |
| ProfileKey* CefBrowserContext::GetProfileKey() const { |
| DCHECK(key_); |
| return key_.get(); |
| } |
| |
| policy::SchemaRegistryService* |
| CefBrowserContext::GetPolicySchemaRegistryService() { |
| NOTREACHED(); |
| return nullptr; |
| } |
| |
| policy::UserCloudPolicyManager* CefBrowserContext::GetUserCloudPolicyManager() { |
| NOTREACHED(); |
| return nullptr; |
| } |
| |
| policy::ProfilePolicyConnector* CefBrowserContext::GetProfilePolicyConnector() { |
| NOTREACHED(); |
| return nullptr; |
| } |
| |
| const policy::ProfilePolicyConnector* |
| CefBrowserContext::GetProfilePolicyConnector() const { |
| NOTREACHED(); |
| return nullptr; |
| } |
| |
| const CefRequestContextSettings& CefBrowserContext::GetSettings() const { |
| return settings_; |
| } |
| |
| HostContentSettingsMap* CefBrowserContext::GetHostContentSettingsMap() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| if (!host_content_settings_map_.get()) { |
| // The |is_incognito_profile| and |is_guest_profile| arguments are |
| // intentionally set to false as they otherwise limit the types of values |
| // that can be stored in the settings map (for example, default values set |
| // via DefaultProvider::SetWebsiteSetting). |
| host_content_settings_map_ = |
| new HostContentSettingsMap(GetPrefs(), false, false, false); |
| |
| // Change the default plugin policy. |
| const base::CommandLine* command_line = |
| base::CommandLine::ForCurrentProcess(); |
| const std::string& plugin_policy_str = |
| command_line->GetSwitchValueASCII(switches::kPluginPolicy); |
| if (!plugin_policy_str.empty()) { |
| ContentSetting plugin_policy = CONTENT_SETTING_ALLOW; |
| if (base::LowerCaseEqualsASCII(plugin_policy_str, |
| switches::kPluginPolicy_Detect)) { |
| plugin_policy = CONTENT_SETTING_DETECT_IMPORTANT_CONTENT; |
| } else if (base::LowerCaseEqualsASCII(plugin_policy_str, |
| switches::kPluginPolicy_Block)) { |
| plugin_policy = CONTENT_SETTING_BLOCK; |
| } |
| host_content_settings_map_->SetDefaultContentSetting( |
| ContentSettingsType::PLUGINS, plugin_policy); |
| } |
| } |
| return host_content_settings_map_.get(); |
| } |
| |
| void CefBrowserContext::AddVisitedURLs(const std::vector<GURL>& urls) { |
| visitedlink_master_->AddURLs(urls); |
| } |
| |
| void CefBrowserContext::RebuildTable( |
| const scoped_refptr<URLEnumerator>& enumerator) { |
| // Called when visited links will not or cannot be loaded from disk. |
| enumerator->OnComplete(true); |
| } |
| |
| void CefBrowserContext::OnRenderFrameCreated( |
| CefRequestContextImpl* request_context, |
| int render_process_id, |
| int render_frame_id, |
| int frame_tree_node_id, |
| bool is_main_frame, |
| bool is_guest_view) { |
| CEF_REQUIRE_UIT(); |
| DCHECK_GE(render_process_id, 0); |
| DCHECK_GE(render_frame_id, 0); |
| DCHECK_GE(frame_tree_node_id, 0); |
| |
| render_id_set_.insert(std::make_pair(render_process_id, render_frame_id)); |
| node_id_set_.insert(frame_tree_node_id); |
| |
| CefRefPtr<CefRequestContextHandler> handler = request_context->GetHandler(); |
| if (handler) { |
| handler_map_.AddHandler(render_process_id, render_frame_id, |
| frame_tree_node_id, handler); |
| |
| if (resource_context_) { |
| // Using base::Unretained() is safe because both this callback and |
| // possible deletion of |resource_context_| will execute on the IO thread, |
| // and this callback will be executed first. |
| CEF_POST_TASK(CEF_IOT, |
| base::Bind(&CefResourceContext::AddHandler, |
| base::Unretained(resource_context_.get()), |
| render_process_id, render_frame_id, |
| frame_tree_node_id, handler)); |
| } |
| } |
| } |
| |
| void CefBrowserContext::OnRenderFrameDeleted( |
| CefRequestContextImpl* request_context, |
| int render_process_id, |
| int render_frame_id, |
| int frame_tree_node_id, |
| bool is_main_frame, |
| bool is_guest_view) { |
| CEF_REQUIRE_UIT(); |
| DCHECK_GE(render_process_id, 0); |
| DCHECK_GE(render_frame_id, 0); |
| DCHECK_GE(frame_tree_node_id, 0); |
| |
| auto it1 = |
| render_id_set_.find(std::make_pair(render_process_id, render_frame_id)); |
| if (it1 != render_id_set_.end()) |
| render_id_set_.erase(it1); |
| |
| auto it2 = node_id_set_.find(frame_tree_node_id); |
| if (it2 != node_id_set_.end()) |
| node_id_set_.erase(it2); |
| |
| CefRefPtr<CefRequestContextHandler> handler = request_context->GetHandler(); |
| if (handler) { |
| handler_map_.RemoveHandler(render_process_id, render_frame_id, |
| frame_tree_node_id); |
| |
| if (resource_context_) { |
| // Using base::Unretained() is safe because both this callback and |
| // possible deletion of |resource_context_| will execute on the IO thread, |
| // and this callback will be executed first. |
| CEF_POST_TASK( |
| CEF_IOT, |
| base::Bind(&CefResourceContext::RemoveHandler, |
| base::Unretained(resource_context_.get()), |
| render_process_id, render_frame_id, frame_tree_node_id)); |
| } |
| } |
| |
| if (is_main_frame) { |
| ClearPluginLoadDecision(render_process_id); |
| } |
| } |
| |
| CefRefPtr<CefRequestContextHandler> CefBrowserContext::GetHandler( |
| int render_process_id, |
| int render_frame_id, |
| int frame_tree_node_id, |
| bool require_frame_match) const { |
| CEF_REQUIRE_UIT(); |
| return handler_map_.GetHandler(render_process_id, render_frame_id, |
| frame_tree_node_id, require_frame_match); |
| } |
| |
| bool CefBrowserContext::IsAssociatedContext(int render_process_id, |
| int render_frame_id, |
| int frame_tree_node_id, |
| bool require_frame_match) const { |
| CEF_REQUIRE_UIT(); |
| |
| if (render_process_id >= 0 && render_frame_id >= 0) { |
| const auto it1 = |
| render_id_set_.find(std::make_pair(render_process_id, render_frame_id)); |
| if (it1 != render_id_set_.end()) |
| return true; |
| } |
| |
| if (frame_tree_node_id >= 0) { |
| const auto it2 = node_id_set_.find(frame_tree_node_id); |
| if (it2 != node_id_set_.end()) |
| return true; |
| } |
| |
| if (render_process_id >= 0 && !require_frame_match) { |
| // Choose an arbitrary handler for the same process. |
| for (const auto& render_ids : render_id_set_) { |
| if (render_ids.first == render_process_id) |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| void CefBrowserContext::AddPluginLoadDecision( |
| int render_process_id, |
| const base::FilePath& plugin_path, |
| bool is_main_frame, |
| const url::Origin& main_frame_origin, |
| chrome::mojom::PluginStatus status) { |
| CEF_REQUIRE_UIT(); |
| DCHECK_GE(render_process_id, 0); |
| DCHECK(!plugin_path.empty()); |
| |
| plugin_load_decision_map_.insert(std::make_pair( |
| std::make_pair(std::make_pair(render_process_id, plugin_path), |
| std::make_pair(is_main_frame, main_frame_origin)), |
| status)); |
| } |
| |
| bool CefBrowserContext::HasPluginLoadDecision( |
| int render_process_id, |
| const base::FilePath& plugin_path, |
| bool is_main_frame, |
| const url::Origin& main_frame_origin, |
| chrome::mojom::PluginStatus* status) const { |
| CEF_REQUIRE_UIT(); |
| DCHECK_GE(render_process_id, 0); |
| DCHECK(!plugin_path.empty()); |
| |
| PluginLoadDecisionMap::const_iterator it = plugin_load_decision_map_.find( |
| std::make_pair(std::make_pair(render_process_id, plugin_path), |
| std::make_pair(is_main_frame, main_frame_origin))); |
| if (it == plugin_load_decision_map_.end()) |
| return false; |
| |
| *status = it->second; |
| return true; |
| } |
| |
| void CefBrowserContext::ClearPluginLoadDecision(int render_process_id) { |
| CEF_REQUIRE_UIT(); |
| |
| if (render_process_id == -1) { |
| plugin_load_decision_map_.clear(); |
| } else { |
| PluginLoadDecisionMap::iterator it = plugin_load_decision_map_.begin(); |
| while (it != plugin_load_decision_map_.end()) { |
| if (it->first.first.first == render_process_id) |
| it = plugin_load_decision_map_.erase(it); |
| else |
| ++it; |
| } |
| } |
| } |
| |
| void CefBrowserContext::RegisterSchemeHandlerFactory( |
| const std::string& scheme_name, |
| const std::string& domain_name, |
| CefRefPtr<CefSchemeHandlerFactory> factory) { |
| if (resource_context_) { |
| // Using base::Unretained() is safe because both this callback and possible |
| // deletion of |resource_context_| will execute on the IO thread, and this |
| // callback will be executed first. |
| CEF_POST_TASK(CEF_IOT, |
| base::Bind(&CefResourceContext::RegisterSchemeHandlerFactory, |
| base::Unretained(resource_context_.get()), |
| scheme_name, domain_name, factory)); |
| } |
| } |
| |
| void CefBrowserContext::ClearSchemeHandlerFactories() { |
| if (resource_context_) { |
| // Using base::Unretained() is safe because both this callback and possible |
| // deletion of |resource_context_| will execute on the IO thread, and this |
| // callback will be executed first. |
| CEF_POST_TASK(CEF_IOT, |
| base::Bind(&CefResourceContext::ClearSchemeHandlerFactories, |
| base::Unretained(resource_context_.get()))); |
| } |
| } |
| |
| network::mojom::NetworkContext* CefBrowserContext::GetNetworkContext() { |
| CEF_REQUIRE_UIT(); |
| return GetDefaultStoragePartition(this)->GetNetworkContext(); |
| } |
| |
| DownloadPrefs* CefBrowserContext::GetDownloadPrefs() { |
| CEF_REQUIRE_UIT(); |
| if (!download_prefs_) { |
| download_prefs_.reset(new DownloadPrefs(this)); |
| } |
| return download_prefs_.get(); |
| } |
| |
| bool CefBrowserContext::IsPrintPreviewSupported() const { |
| CEF_REQUIRE_UIT(); |
| if (!extensions::PrintPreviewEnabled()) |
| return false; |
| |
| return !GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled); |
| } |
| |
| CefMediaRouterManager* CefBrowserContext::GetMediaRouterManager() { |
| CEF_REQUIRE_UIT(); |
| if (!media_router_manager_) { |
| media_router_manager_.reset(new CefMediaRouterManager(this)); |
| } |
| return media_router_manager_.get(); |
| } |