1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "libcef/browser/iothread_state.h"
6
7 #include "libcef/browser/net/scheme_handler.h"
8 #include "libcef/browser/thread_util.h"
9 #include "libcef/common/net/scheme_registration.h"
10
11 #include "base/i18n/case_conversion.h"
12 #include "base/logging.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "content/browser/resource_context_impl.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/global_routing_id.h"
18
CefIOThreadState()19 CefIOThreadState::CefIOThreadState() {
20 // Using base::Unretained() is safe because both this callback and possible
21 // deletion of |this| will execute on the IO thread, and this callback will
22 // be executed first.
23 CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefIOThreadState::InitOnIOThread,
24 base::Unretained(this)));
25 }
26
~CefIOThreadState()27 CefIOThreadState::~CefIOThreadState() {
28 CEF_REQUIRE_IOT();
29 }
30
AddHandler(const content::GlobalRenderFrameHostId & global_id,CefRefPtr<CefRequestContextHandler> handler)31 void CefIOThreadState::AddHandler(
32 const content::GlobalRenderFrameHostId& global_id,
33 CefRefPtr<CefRequestContextHandler> handler) {
34 CEF_REQUIRE_IOT();
35 handler_map_.AddHandler(global_id, handler);
36 }
37
RemoveHandler(const content::GlobalRenderFrameHostId & global_id)38 void CefIOThreadState::RemoveHandler(
39 const content::GlobalRenderFrameHostId& global_id) {
40 CEF_REQUIRE_IOT();
41 handler_map_.RemoveHandler(global_id);
42 }
43
GetHandler(const content::GlobalRenderFrameHostId & global_id,bool require_frame_match) const44 CefRefPtr<CefRequestContextHandler> CefIOThreadState::GetHandler(
45 const content::GlobalRenderFrameHostId& global_id,
46 bool require_frame_match) const {
47 CEF_REQUIRE_IOT();
48 return handler_map_.GetHandler(global_id, require_frame_match);
49 }
50
RegisterSchemeHandlerFactory(const std::string & scheme_name,const std::string & domain_name,CefRefPtr<CefSchemeHandlerFactory> factory)51 void CefIOThreadState::RegisterSchemeHandlerFactory(
52 const std::string& scheme_name,
53 const std::string& domain_name,
54 CefRefPtr<CefSchemeHandlerFactory> factory) {
55 CEF_REQUIRE_IOT();
56
57 const std::string& scheme_lower = base::ToLowerASCII(scheme_name);
58 std::string domain_lower;
59
60 // Hostname is only supported for standard schemes.
61 if (scheme::IsStandardScheme(scheme_lower)) {
62 // Hostname might contain Unicode characters.
63 domain_lower =
64 base::UTF16ToUTF8(base::i18n::ToLower(base::UTF8ToUTF16(domain_name)));
65 }
66
67 const auto key = std::make_pair(scheme_lower, domain_lower);
68
69 if (factory) {
70 // Add or replace the factory.
71 scheme_handler_factory_map_[key] = factory;
72 } else {
73 // Remove the existing factory, if any.
74 auto it = scheme_handler_factory_map_.find(key);
75 if (it != scheme_handler_factory_map_.end())
76 scheme_handler_factory_map_.erase(it);
77 }
78 }
79
ClearSchemeHandlerFactories()80 void CefIOThreadState::ClearSchemeHandlerFactories() {
81 CEF_REQUIRE_IOT();
82
83 scheme_handler_factory_map_.clear();
84
85 // Restore the default internal handlers.
86 scheme::RegisterInternalHandlers(this);
87 }
88
GetSchemeHandlerFactory(const GURL & url)89 CefRefPtr<CefSchemeHandlerFactory> CefIOThreadState::GetSchemeHandlerFactory(
90 const GURL& url) {
91 CEF_REQUIRE_IOT();
92
93 if (scheme_handler_factory_map_.empty())
94 return nullptr;
95
96 const std::string& scheme_lower = url.scheme();
97 const std::string& domain_lower =
98 url.IsStandard() ? url.host() : std::string();
99
100 if (!domain_lower.empty()) {
101 // Sanity check.
102 DCHECK(scheme::IsStandardScheme(scheme_lower)) << scheme_lower;
103
104 // Try for a match with hostname first.
105 const auto it = scheme_handler_factory_map_.find(
106 std::make_pair(scheme_lower, domain_lower));
107 if (it != scheme_handler_factory_map_.end())
108 return it->second;
109 }
110
111 // Try for a match with no specified hostname.
112 const auto it = scheme_handler_factory_map_.find(
113 std::make_pair(scheme_lower, std::string()));
114 if (it != scheme_handler_factory_map_.end())
115 return it->second;
116
117 return nullptr;
118 }
119
InitOnIOThread()120 void CefIOThreadState::InitOnIOThread() {
121 CEF_REQUIRE_IOT();
122
123 // Add the default internal handlers.
124 scheme::RegisterInternalHandlers(this);
125 }
126