mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-04-25 07:58:44 +02:00
Add NetworkService support for chrome and chrome-devtools schemes (see issue #2622).
Known behavior changes: - Unsupported chrome hosts no longer redirect to chrome://version. To test: All tests pass with NetworkService disabled. WebUITest.* and V8Test.* tests pass with NetworkService enabled.
This commit is contained in:
parent
9fd6c8a1ee
commit
370cc028cb
@ -91,6 +91,7 @@
|
|||||||
#include "content/public/common/content_switches.h"
|
#include "content/public/common/content_switches.h"
|
||||||
#include "content/public/common/service_names.mojom.h"
|
#include "content/public/common/service_names.mojom.h"
|
||||||
#include "content/public/common/storage_quota_params.h"
|
#include "content/public/common/storage_quota_params.h"
|
||||||
|
#include "content/public/common/url_constants.h"
|
||||||
#include "content/public/common/user_agent.h"
|
#include "content/public/common/user_agent.h"
|
||||||
#include "content/public/common/web_preferences.h"
|
#include "content/public/common/web_preferences.h"
|
||||||
#include "extensions/browser/extension_message_filter.h"
|
#include "extensions/browser/extension_message_filter.h"
|
||||||
@ -588,6 +589,33 @@ bool CefContentBrowserClient::DoesSiteRequireDedicatedProcess(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefContentBrowserClient::GetAdditionalWebUISchemes(
|
||||||
|
std::vector<std::string>* additional_schemes) {
|
||||||
|
// Any schemes listed here are treated as WebUI schemes but do not get WebUI
|
||||||
|
// bindings. Also, view-source is allowed for these schemes. WebUI schemes
|
||||||
|
// will not be passed to HandleExternalProtocol.
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefContentBrowserClient::GetAdditionalViewSourceSchemes(
|
||||||
|
std::vector<std::string>* additional_schemes) {
|
||||||
|
GetAdditionalWebUISchemes(additional_schemes);
|
||||||
|
|
||||||
|
additional_schemes->push_back(extensions::kExtensionScheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
||||||
|
std::vector<std::string>* additional_allowed_schemes) {
|
||||||
|
ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
||||||
|
additional_allowed_schemes);
|
||||||
|
additional_allowed_schemes->push_back(content::kChromeDevToolsScheme);
|
||||||
|
additional_allowed_schemes->push_back(content::kChromeUIScheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
|
||||||
|
const url::Origin& origin) {
|
||||||
|
return scheme::IsWebUIAllowedToMakeNetworkRequests(origin);
|
||||||
|
}
|
||||||
|
|
||||||
bool CefContentBrowserClient::IsHandledURL(const GURL& url) {
|
bool CefContentBrowserClient::IsHandledURL(const GURL& url) {
|
||||||
if (!url.is_valid())
|
if (!url.is_valid())
|
||||||
return false;
|
return false;
|
||||||
|
@ -50,6 +50,13 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
|||||||
const GURL& effective_url) override;
|
const GURL& effective_url) override;
|
||||||
bool DoesSiteRequireDedicatedProcess(content::BrowserContext* browser_context,
|
bool DoesSiteRequireDedicatedProcess(content::BrowserContext* browser_context,
|
||||||
const GURL& effective_site_url) override;
|
const GURL& effective_site_url) override;
|
||||||
|
void GetAdditionalWebUISchemes(
|
||||||
|
std::vector<std::string>* additional_schemes) override;
|
||||||
|
void GetAdditionalViewSourceSchemes(
|
||||||
|
std::vector<std::string>* additional_schemes) override;
|
||||||
|
void GetAdditionalAllowedSchemesForFileSystem(
|
||||||
|
std::vector<std::string>* additional_allowed_schemes) override;
|
||||||
|
bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
|
||||||
bool IsHandledURL(const GURL& url) override;
|
bool IsHandledURL(const GURL& url) override;
|
||||||
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
|
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
|
||||||
void SiteInstanceDeleting(content::SiteInstance* site_instance) override;
|
void SiteInstanceDeleting(content::SiteInstance* site_instance) override;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "content/browser/frame_host/debug_urls.h"
|
#include "content/browser/frame_host/debug_urls.h"
|
||||||
#include "content/browser/webui/content_web_ui_controller_factory.h"
|
#include "content/browser/webui/content_web_ui_controller_factory.h"
|
||||||
#include "content/public/browser/browser_url_handler.h"
|
#include "content/public/browser/browser_url_handler.h"
|
||||||
|
#include "content/public/browser/url_data_source.h"
|
||||||
#include "content/public/browser/web_ui_controller.h"
|
#include "content/public/browser/web_ui_controller.h"
|
||||||
#include "content/public/common/url_constants.h"
|
#include "content/public/common/url_constants.h"
|
||||||
#include "content/public/common/url_utils.h"
|
#include "content/public/common/url_utils.h"
|
||||||
@ -57,6 +58,15 @@ const char kChromeUIExtensionsSupportHost[] = "extensions-support";
|
|||||||
const char kChromeUILicenseHost[] = "license";
|
const char kChromeUILicenseHost[] = "license";
|
||||||
const char kChromeUIWebUIHostsHost[] = "webui-hosts";
|
const char kChromeUIWebUIHostsHost[] = "webui-hosts";
|
||||||
|
|
||||||
|
// TODO(network): Consider handling content::kChromeDevToolsScheme via WebUI
|
||||||
|
// (DevToolsUI class) with the following changes:
|
||||||
|
// 1. Add an entry for content::kChromeDevToolsScheme in
|
||||||
|
// CefContentBrowserClient::GetAdditionalWebUISchemes.
|
||||||
|
// 2. Allow the scheme in CefWebUIControllerFactory::AllowWebUIForURL.
|
||||||
|
// 3. Add an entry for chrome::kChromeUIDevToolsHost in kAllowedWebUIHosts and
|
||||||
|
// kUnlistedHosts.
|
||||||
|
// 4. Remove scheme::RegisterInternalHandlers and related plumbing.
|
||||||
|
|
||||||
// Chrome hosts implemented by WebUI.
|
// Chrome hosts implemented by WebUI.
|
||||||
// Some WebUI handlers have Chrome dependencies that may fail in CEF without
|
// Some WebUI handlers have Chrome dependencies that may fail in CEF without
|
||||||
// additional changes. Do not add new hosts to this list without also manually
|
// additional changes. Do not add new hosts to this list without also manually
|
||||||
@ -66,9 +76,11 @@ const char* kAllowedWebUIHosts[] = {
|
|||||||
chrome::kChromeUIAccessibilityHost,
|
chrome::kChromeUIAccessibilityHost,
|
||||||
content::kChromeUIBlobInternalsHost,
|
content::kChromeUIBlobInternalsHost,
|
||||||
chrome::kChromeUICreditsHost,
|
chrome::kChromeUICreditsHost,
|
||||||
|
kChromeUIExtensionsSupportHost,
|
||||||
content::kChromeUIGpuHost,
|
content::kChromeUIGpuHost,
|
||||||
content::kChromeUIHistogramHost,
|
content::kChromeUIHistogramHost,
|
||||||
content::kChromeUIIndexedDBInternalsHost,
|
content::kChromeUIIndexedDBInternalsHost,
|
||||||
|
kChromeUILicenseHost,
|
||||||
content::kChromeUIMediaInternalsHost,
|
content::kChromeUIMediaInternalsHost,
|
||||||
chrome::kChromeUINetExportHost,
|
chrome::kChromeUINetExportHost,
|
||||||
chrome::kChromeUINetInternalsHost,
|
chrome::kChromeUINetInternalsHost,
|
||||||
@ -78,7 +90,9 @@ const char* kAllowedWebUIHosts[] = {
|
|||||||
content::kChromeUIServiceWorkerInternalsHost,
|
content::kChromeUIServiceWorkerInternalsHost,
|
||||||
chrome::kChromeUISystemInfoHost,
|
chrome::kChromeUISystemInfoHost,
|
||||||
content::kChromeUITracingHost,
|
content::kChromeUITracingHost,
|
||||||
|
chrome::kChromeUIVersionHost,
|
||||||
content::kChromeUIWebRTCInternalsHost,
|
content::kChromeUIWebRTCInternalsHost,
|
||||||
|
kChromeUIWebUIHostsHost,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hosts that don't have useful output when linked directly. They'll be excluded
|
// Hosts that don't have useful output when linked directly. They'll be excluded
|
||||||
@ -119,15 +133,8 @@ ChromeHostId GetChromeHostId(const std::string& host) {
|
|||||||
return CHROME_UNKNOWN;
|
return CHROME_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns CEF and WebUI hosts. Does not include chrome debug hosts (for
|
// Returns WebUI hosts. Does not include chrome debug hosts (for crashing, etc).
|
||||||
// crashing, etc).
|
|
||||||
void GetAllowedHosts(std::vector<std::string>* hosts) {
|
void GetAllowedHosts(std::vector<std::string>* hosts) {
|
||||||
// Hosts implemented by CEF.
|
|
||||||
for (size_t i = 0; i < sizeof(kAllowedCefHosts) / sizeof(kAllowedCefHosts[0]);
|
|
||||||
++i) {
|
|
||||||
hosts->push_back(kAllowedCefHosts[i].host);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explicitly whitelisted WebUI hosts.
|
// Explicitly whitelisted WebUI hosts.
|
||||||
for (size_t i = 0;
|
for (size_t i = 0;
|
||||||
i < sizeof(kAllowedWebUIHosts) / sizeof(kAllowedWebUIHosts[0]); ++i) {
|
i < sizeof(kAllowedWebUIHosts) / sizeof(kAllowedWebUIHosts[0]); ++i) {
|
||||||
@ -199,6 +206,327 @@ void GetDebugURLs(std::vector<std::string>* urls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetOSType() {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
return "Windows";
|
||||||
|
#elif defined(OS_MACOSX)
|
||||||
|
return "Mac OS X";
|
||||||
|
#elif defined(OS_CHROMEOS)
|
||||||
|
return "Chromium OS";
|
||||||
|
#elif defined(OS_ANDROID)
|
||||||
|
return "Android";
|
||||||
|
#elif defined(OS_LINUX)
|
||||||
|
return "Linux";
|
||||||
|
#elif defined(OS_FREEBSD)
|
||||||
|
return "FreeBSD";
|
||||||
|
#elif defined(OS_OPENBSD)
|
||||||
|
return "OpenBSD";
|
||||||
|
#elif defined(OS_SOLARIS)
|
||||||
|
return "Solaris";
|
||||||
|
#else
|
||||||
|
return "Unknown";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetCommandLine() {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
return base::WideToUTF8(
|
||||||
|
base::CommandLine::ForCurrentProcess()->GetCommandLineString());
|
||||||
|
#elif defined(OS_POSIX)
|
||||||
|
std::string command_line = "";
|
||||||
|
typedef std::vector<std::string> ArgvList;
|
||||||
|
const ArgvList& argv = base::CommandLine::ForCurrentProcess()->argv();
|
||||||
|
for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++)
|
||||||
|
command_line += " " + *iter;
|
||||||
|
// TODO(viettrungluu): |command_line| could really have any encoding, whereas
|
||||||
|
// below we assumes it's UTF-8.
|
||||||
|
return command_line;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetModulePath() {
|
||||||
|
base::FilePath path;
|
||||||
|
if (base::PathService::Get(base::FILE_MODULE, &path))
|
||||||
|
return CefString(path.value());
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemplateParser {
|
||||||
|
public:
|
||||||
|
TemplateParser() : ident_start_("$$"), ident_end_("$$") {}
|
||||||
|
|
||||||
|
TemplateParser(const std::string& ident_start, const std::string& ident_end)
|
||||||
|
: ident_start_(ident_start), ident_end_(ident_end) {}
|
||||||
|
|
||||||
|
void Add(const std::string& key, const std::string& value) {
|
||||||
|
values_.insert(std::make_pair(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parse(std::string* tmpl) {
|
||||||
|
int start_pos, end_pos = 0;
|
||||||
|
int ident_start_len = ident_start_.length();
|
||||||
|
int ident_end_len = ident_end_.length();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
start_pos = tmpl->find(ident_start_, end_pos);
|
||||||
|
if (start_pos >= 0) {
|
||||||
|
end_pos = tmpl->find(ident_end_, start_pos + ident_start_len);
|
||||||
|
if (end_pos >= 0) {
|
||||||
|
// Found an identifier. Check if a substitution exists.
|
||||||
|
std::string key = tmpl->substr(start_pos + ident_start_len,
|
||||||
|
end_pos - start_pos - ident_start_len);
|
||||||
|
KeyMap::const_iterator it = values_.find(key);
|
||||||
|
if (it != values_.end()) {
|
||||||
|
// Peform the substitution.
|
||||||
|
tmpl->replace(start_pos, end_pos + ident_end_len - start_pos,
|
||||||
|
it->second);
|
||||||
|
end_pos = start_pos + it->second.length();
|
||||||
|
} else {
|
||||||
|
// Leave the unknown identifier in place.
|
||||||
|
end_pos += ident_end_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_pos >= static_cast<int>(tmpl->length()) - ident_start_len -
|
||||||
|
ident_end_len) {
|
||||||
|
// Not enough room remaining for more identifiers.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No end identifier found.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No start identifier found.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map<std::string, std::string> KeyMap;
|
||||||
|
KeyMap values_;
|
||||||
|
std::string ident_start_;
|
||||||
|
std::string ident_end_;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool OnExtensionsSupportUI(std::string* mime_type, std::string* output) {
|
||||||
|
static const char kDevURL[] = "https://developer.chrome.com/extensions/";
|
||||||
|
|
||||||
|
std::string html =
|
||||||
|
"<html>\n<head><title>Extensions Support</title></head>\n"
|
||||||
|
"<body bgcolor=\"white\"><h3>Supported Chrome Extensions "
|
||||||
|
"APIs</h3>\nFollow <a "
|
||||||
|
"href=\"https://bitbucket.org/chromiumembedded/cef/issues/1947\" "
|
||||||
|
"target=\"new\">issue #1947</a> for development progress.\n<ul>\n";
|
||||||
|
|
||||||
|
bool has_top_level_name = false;
|
||||||
|
for (size_t i = 0; kSupportedAPIs[i] != nullptr; ++i) {
|
||||||
|
const std::string& api_name = kSupportedAPIs[i];
|
||||||
|
if (api_name.find("Private") != std::string::npos) {
|
||||||
|
// Don't list private APIs.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t dot_pos = api_name.find('.');
|
||||||
|
if (dot_pos == std::string::npos) {
|
||||||
|
if (has_top_level_name) {
|
||||||
|
// End the previous top-level API entry.
|
||||||
|
html += "</ul></li>\n";
|
||||||
|
} else {
|
||||||
|
has_top_level_name = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a new top-level API entry.
|
||||||
|
html += "<li><a href=\"" + std::string(kDevURL) + api_name +
|
||||||
|
"\" target=\"new\">" + api_name + "</a><ul>\n";
|
||||||
|
} else {
|
||||||
|
// Function name.
|
||||||
|
const std::string& group_name = api_name.substr(0, dot_pos);
|
||||||
|
const std::string& function_name = api_name.substr(dot_pos + 1);
|
||||||
|
html += "\t<li><a href=\"" + std::string(kDevURL) + group_name +
|
||||||
|
"#method-" + function_name + "\" target=\"new\">" + api_name +
|
||||||
|
"</a></li>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_top_level_name) {
|
||||||
|
// End the last top-level API entry.
|
||||||
|
html += "</ul></li>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
html += "</ul>\n</body>\n</html>";
|
||||||
|
|
||||||
|
*mime_type = "text/html";
|
||||||
|
*output = html;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnLicenseUI(std::string* mime_type, std::string* output) {
|
||||||
|
base::StringPiece piece = CefContentClient::Get()->GetDataResource(
|
||||||
|
IDR_CEF_LICENSE_TXT, ui::SCALE_FACTOR_NONE);
|
||||||
|
if (piece.empty()) {
|
||||||
|
NOTREACHED() << "Failed to load license txt resource.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mime_type = "text/html";
|
||||||
|
*output = "<html><head><title>License</title></head><body><pre>" +
|
||||||
|
piece.as_string() + "</pre></body></html>";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnVersionUI(Profile* profile,
|
||||||
|
std::string* mime_type,
|
||||||
|
std::string* output) {
|
||||||
|
base::StringPiece piece = CefContentClient::Get()->GetDataResource(
|
||||||
|
IDR_CEF_VERSION_HTML, ui::SCALE_FACTOR_NONE);
|
||||||
|
if (piece.empty()) {
|
||||||
|
NOTREACHED() << "Failed to load version html resource.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateParser parser;
|
||||||
|
parser.Add("YEAR", MAKE_STRING(COPYRIGHT_YEAR));
|
||||||
|
parser.Add("CEF", CEF_VERSION);
|
||||||
|
parser.Add("CHROMIUM",
|
||||||
|
base::StringPrintf("%d.%d.%d.%d", CHROME_VERSION_MAJOR,
|
||||||
|
CHROME_VERSION_MINOR, CHROME_VERSION_BUILD,
|
||||||
|
CHROME_VERSION_PATCH));
|
||||||
|
parser.Add("OS", GetOSType());
|
||||||
|
parser.Add("WEBKIT", content::GetWebKitVersion());
|
||||||
|
parser.Add("JAVASCRIPT", v8::V8::GetVersion());
|
||||||
|
parser.Add("FLASH", std::string()); // Value populated asynchronously.
|
||||||
|
parser.Add("USERAGENT", CefContentClient::Get()->browser()->GetUserAgent());
|
||||||
|
parser.Add("COMMANDLINE", GetCommandLine());
|
||||||
|
parser.Add("MODULEPATH", GetModulePath());
|
||||||
|
parser.Add("CACHEPATH", CefString(profile->GetPath().value()));
|
||||||
|
|
||||||
|
std::string tmpl = piece.as_string();
|
||||||
|
parser.Parse(&tmpl);
|
||||||
|
|
||||||
|
*mime_type = "text/html";
|
||||||
|
*output = tmpl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnWebUIHostsUI(std::string* mime_type, std::string* output) {
|
||||||
|
std::string html =
|
||||||
|
"<html>\n<head><title>WebUI Hosts</title></head>\n"
|
||||||
|
"<body bgcolor=\"white\"><h3>WebUI Hosts</h3>\n<ul>\n";
|
||||||
|
|
||||||
|
std::vector<std::string> list;
|
||||||
|
GetAllowedHosts(&list);
|
||||||
|
std::sort(list.begin(), list.end());
|
||||||
|
|
||||||
|
for (size_t i = 0U; i < list.size(); ++i) {
|
||||||
|
if (IsUnlistedHost(list[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
html += "<li><a href=\"chrome://" + list[i] + "\">chrome://" + list[i] +
|
||||||
|
"</a></li>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
list.clear();
|
||||||
|
GetDebugURLs(&list);
|
||||||
|
std::sort(list.begin(), list.end());
|
||||||
|
|
||||||
|
html +=
|
||||||
|
"</ul>\n<h3>For Debug</h3>\n"
|
||||||
|
"<p>The following pages are for debugging purposes only. Because they "
|
||||||
|
"crash or hang the renderer, they're not linked directly; you can type "
|
||||||
|
"them into the address bar if you need them.</p>\n<ul>\n";
|
||||||
|
for (size_t i = 0U; i < list.size(); ++i) {
|
||||||
|
html += "<li>" + std::string(list[i]) + "</li>\n";
|
||||||
|
}
|
||||||
|
html += "</ul>\n";
|
||||||
|
|
||||||
|
html += "</body>\n</html>";
|
||||||
|
|
||||||
|
*mime_type = "text/html";
|
||||||
|
*output = html;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content::WebUI::TypeID kCefWebUITypeID = &kCefWebUITypeID;
|
||||||
|
|
||||||
|
class CefURLDataSource : public content::URLDataSource {
|
||||||
|
public:
|
||||||
|
CefURLDataSource(const std::string& host,
|
||||||
|
ChromeHostId host_id,
|
||||||
|
Profile* profile)
|
||||||
|
: host_(host), host_id_(host_id), profile_(profile) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
output_ = new base::RefCountedString();
|
||||||
|
bool handled = false;
|
||||||
|
switch (host_id_) {
|
||||||
|
case CHROME_EXTENSIONS_SUPPORT:
|
||||||
|
handled = OnExtensionsSupportUI(&mime_type_, &output_->data());
|
||||||
|
break;
|
||||||
|
case CHROME_LICENSE:
|
||||||
|
handled = OnLicenseUI(&mime_type_, &output_->data());
|
||||||
|
break;
|
||||||
|
case CHROME_VERSION:
|
||||||
|
handled = OnVersionUI(profile_, &mime_type_, &output_->data());
|
||||||
|
break;
|
||||||
|
case CHROME_WEBUI_HOSTS:
|
||||||
|
handled = OnWebUIHostsUI(&mime_type_, &output_->data());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DCHECK(handled) << "Unhandled WebUI host: " << host;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CefURLDataSource() override = default;
|
||||||
|
|
||||||
|
// content::URLDataSource implementation.
|
||||||
|
std::string GetSource() const override { return host_; }
|
||||||
|
|
||||||
|
void StartDataRequest(
|
||||||
|
const std::string& path,
|
||||||
|
const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
|
||||||
|
const content::URLDataSource::GotDataCallback& callback) override {
|
||||||
|
callback.Run(output_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetMimeType(const std::string& path) const override {
|
||||||
|
return mime_type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AllowCaching() const override { return false; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string host_;
|
||||||
|
const ChromeHostId host_id_;
|
||||||
|
Profile* const profile_;
|
||||||
|
|
||||||
|
std::string mime_type_;
|
||||||
|
scoped_refptr<base::RefCountedString> output_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefURLDataSource);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CefWebUIController : public content::WebUIController {
|
||||||
|
public:
|
||||||
|
CefWebUIController(content::WebUI* web_ui,
|
||||||
|
const std::string& host,
|
||||||
|
ChromeHostId host_id)
|
||||||
|
: content::WebUIController(web_ui) {
|
||||||
|
Profile* profile = Profile::FromWebUI(web_ui);
|
||||||
|
content::URLDataSource::Add(
|
||||||
|
profile, std::make_unique<CefURLDataSource>(host, host_id, profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
~CefWebUIController() override = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefWebUIController);
|
||||||
|
};
|
||||||
|
|
||||||
// Intercepts all WebUI calls and either blocks them or forwards them to the
|
// Intercepts all WebUI calls and either blocks them or forwards them to the
|
||||||
// Content or Chrome WebUI factory as appropriate.
|
// Content or Chrome WebUI factory as appropriate.
|
||||||
class CefWebUIControllerFactory : public content::WebUIControllerFactory {
|
class CefWebUIControllerFactory : public content::WebUIControllerFactory {
|
||||||
@ -214,6 +542,19 @@ class CefWebUIControllerFactory : public content::WebUIControllerFactory {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if WebUI is allowed to make network requests.
|
||||||
|
static bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) {
|
||||||
|
if (!AllowWebUIForURL(origin.GetURL()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ChromeWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(
|
||||||
|
origin)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<content::WebUIController> CreateWebUIControllerForURL(
|
std::unique_ptr<content::WebUIController> CreateWebUIControllerForURL(
|
||||||
content::WebUI* web_ui,
|
content::WebUI* web_ui,
|
||||||
const GURL& url) const override {
|
const GURL& url) const override {
|
||||||
@ -221,6 +562,11 @@ class CefWebUIControllerFactory : public content::WebUIControllerFactory {
|
|||||||
if (!AllowWebUIForURL(url))
|
if (!AllowWebUIForURL(url))
|
||||||
return controller;
|
return controller;
|
||||||
|
|
||||||
|
const auto host_id = GetChromeHostId(url.host());
|
||||||
|
if (host_id != CHROME_UNKNOWN) {
|
||||||
|
return std::make_unique<CefWebUIController>(web_ui, url.host(), host_id);
|
||||||
|
}
|
||||||
|
|
||||||
controller = content::ContentWebUIControllerFactory::GetInstance()
|
controller = content::ContentWebUIControllerFactory::GetInstance()
|
||||||
->CreateWebUIControllerForURL(web_ui, url);
|
->CreateWebUIControllerForURL(web_ui, url);
|
||||||
if (controller.get())
|
if (controller.get())
|
||||||
@ -236,6 +582,11 @@ class CefWebUIControllerFactory : public content::WebUIControllerFactory {
|
|||||||
if (!AllowWebUIForURL(url))
|
if (!AllowWebUIForURL(url))
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
|
const auto host_id = GetChromeHostId(url.host());
|
||||||
|
if (host_id != CHROME_UNKNOWN) {
|
||||||
|
return kCefWebUITypeID;
|
||||||
|
}
|
||||||
|
|
||||||
type = content::ContentWebUIControllerFactory::GetInstance()->GetWebUIType(
|
type = content::ContentWebUIControllerFactory::GetInstance()->GetWebUIType(
|
||||||
browser_context, url);
|
browser_context, url);
|
||||||
if (type != content::WebUI::kNoWebUI)
|
if (type != content::WebUI::kNoWebUI)
|
||||||
@ -254,6 +605,11 @@ class CefWebUIControllerFactory : public content::WebUIControllerFactory {
|
|||||||
if (!AllowWebUIForURL(url))
|
if (!AllowWebUIForURL(url))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const auto host_id = GetChromeHostId(url.host());
|
||||||
|
if (host_id != CHROME_UNKNOWN) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (content::ContentWebUIControllerFactory::GetInstance()->UseWebUIForURL(
|
if (content::ContentWebUIControllerFactory::GetInstance()->UseWebUIForURL(
|
||||||
browser_context, url) ||
|
browser_context, url) ||
|
||||||
ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL(
|
ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL(
|
||||||
@ -269,6 +625,12 @@ class CefWebUIControllerFactory : public content::WebUIControllerFactory {
|
|||||||
if (!AllowWebUIForURL(url))
|
if (!AllowWebUIForURL(url))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const auto host_id = GetChromeHostId(url.host());
|
||||||
|
if (host_id != CHROME_UNKNOWN) {
|
||||||
|
// TODO(network): Use WebUI bindings to implement DidFinishChromeLoad.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (content::ContentWebUIControllerFactory::GetInstance()
|
if (content::ContentWebUIControllerFactory::GetInstance()
|
||||||
->UseWebUIBindingsForURL(browser_context, url) ||
|
->UseWebUIBindingsForURL(browser_context, url) ||
|
||||||
ChromeWebUIControllerFactory::GetInstance()->UseWebUIBindingsForURL(
|
ChromeWebUIControllerFactory::GetInstance()->UseWebUIBindingsForURL(
|
||||||
@ -396,307 +758,6 @@ CefWebUIControllerFactory* CefWebUIControllerFactory::GetInstance() {
|
|||||||
return &g_web_ui_controller_factory.Get();
|
return &g_web_ui_controller_factory.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetOSType() {
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
return "Windows";
|
|
||||||
#elif defined(OS_MACOSX)
|
|
||||||
return "Mac OS X";
|
|
||||||
#elif defined(OS_CHROMEOS)
|
|
||||||
return "Chromium OS";
|
|
||||||
#elif defined(OS_ANDROID)
|
|
||||||
return "Android";
|
|
||||||
#elif defined(OS_LINUX)
|
|
||||||
return "Linux";
|
|
||||||
#elif defined(OS_FREEBSD)
|
|
||||||
return "FreeBSD";
|
|
||||||
#elif defined(OS_OPENBSD)
|
|
||||||
return "OpenBSD";
|
|
||||||
#elif defined(OS_SOLARIS)
|
|
||||||
return "Solaris";
|
|
||||||
#else
|
|
||||||
return "Unknown";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetCommandLine() {
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
return base::WideToUTF8(
|
|
||||||
base::CommandLine::ForCurrentProcess()->GetCommandLineString());
|
|
||||||
#elif defined(OS_POSIX)
|
|
||||||
std::string command_line = "";
|
|
||||||
typedef std::vector<std::string> ArgvList;
|
|
||||||
const ArgvList& argv = base::CommandLine::ForCurrentProcess()->argv();
|
|
||||||
for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++)
|
|
||||||
command_line += " " + *iter;
|
|
||||||
// TODO(viettrungluu): |command_line| could really have any encoding, whereas
|
|
||||||
// below we assumes it's UTF-8.
|
|
||||||
return command_line;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetModulePath() {
|
|
||||||
base::FilePath path;
|
|
||||||
if (base::PathService::Get(base::FILE_MODULE, &path))
|
|
||||||
return CefString(path.value());
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
class TemplateParser {
|
|
||||||
public:
|
|
||||||
TemplateParser() : ident_start_("$$"), ident_end_("$$") {}
|
|
||||||
|
|
||||||
TemplateParser(const std::string& ident_start, const std::string& ident_end)
|
|
||||||
: ident_start_(ident_start), ident_end_(ident_end) {}
|
|
||||||
|
|
||||||
void Add(const std::string& key, const std::string& value) {
|
|
||||||
values_.insert(std::make_pair(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parse(std::string* tmpl) {
|
|
||||||
int start_pos, end_pos = 0;
|
|
||||||
int ident_start_len = ident_start_.length();
|
|
||||||
int ident_end_len = ident_end_.length();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
start_pos = tmpl->find(ident_start_, end_pos);
|
|
||||||
if (start_pos >= 0) {
|
|
||||||
end_pos = tmpl->find(ident_end_, start_pos + ident_start_len);
|
|
||||||
if (end_pos >= 0) {
|
|
||||||
// Found an identifier. Check if a substitution exists.
|
|
||||||
std::string key = tmpl->substr(start_pos + ident_start_len,
|
|
||||||
end_pos - start_pos - ident_start_len);
|
|
||||||
KeyMap::const_iterator it = values_.find(key);
|
|
||||||
if (it != values_.end()) {
|
|
||||||
// Peform the substitution.
|
|
||||||
tmpl->replace(start_pos, end_pos + ident_end_len - start_pos,
|
|
||||||
it->second);
|
|
||||||
end_pos = start_pos + it->second.length();
|
|
||||||
} else {
|
|
||||||
// Leave the unknown identifier in place.
|
|
||||||
end_pos += ident_end_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end_pos >= static_cast<int>(tmpl->length()) - ident_start_len -
|
|
||||||
ident_end_len) {
|
|
||||||
// Not enough room remaining for more identifiers.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No end identifier found.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No start identifier found.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::map<std::string, std::string> KeyMap;
|
|
||||||
KeyMap values_;
|
|
||||||
std::string ident_start_;
|
|
||||||
std::string ident_end_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Delegate : public InternalHandlerDelegate {
|
|
||||||
public:
|
|
||||||
Delegate() {}
|
|
||||||
|
|
||||||
bool OnRequest(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefRequest> request,
|
|
||||||
Action* action) override {
|
|
||||||
GURL url = GURL(request->GetURL().ToString());
|
|
||||||
std::string path = url.path();
|
|
||||||
if (path.length() > 0)
|
|
||||||
path = path.substr(1);
|
|
||||||
|
|
||||||
bool handled = false;
|
|
||||||
|
|
||||||
ChromeHostId host_id = GetChromeHostId(url.host());
|
|
||||||
switch (host_id) {
|
|
||||||
case CHROME_EXTENSIONS_SUPPORT:
|
|
||||||
handled = OnExtensionsSupport(action);
|
|
||||||
break;
|
|
||||||
case CHROME_LICENSE:
|
|
||||||
handled = OnLicense(action);
|
|
||||||
break;
|
|
||||||
case CHROME_VERSION:
|
|
||||||
handled = OnVersion(browser, action);
|
|
||||||
break;
|
|
||||||
case CHROME_WEBUI_HOSTS:
|
|
||||||
handled = OnWebUIHosts(action);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!handled && host_id != CHROME_VERSION) {
|
|
||||||
LOG(INFO) << "Reguest for unknown chrome resource: "
|
|
||||||
<< url.spec().c_str();
|
|
||||||
|
|
||||||
action->redirect_url =
|
|
||||||
GURL(std::string(kChromeURL) + chrome::kChromeUIVersionHost);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnExtensionsSupport(Action* action) {
|
|
||||||
static const char kDevURL[] = "https://developer.chrome.com/extensions/";
|
|
||||||
|
|
||||||
std::string html =
|
|
||||||
"<html>\n<head><title>Extensions Support</title></head>\n"
|
|
||||||
"<body bgcolor=\"white\"><h3>Supported Chrome Extensions "
|
|
||||||
"APIs</h3>\nFollow <a "
|
|
||||||
"href=\"https://bitbucket.org/chromiumembedded/cef/issues/1947\" "
|
|
||||||
"target=\"new\">issue #1947</a> for development progress.\n<ul>\n";
|
|
||||||
|
|
||||||
bool has_top_level_name = false;
|
|
||||||
for (size_t i = 0; kSupportedAPIs[i] != nullptr; ++i) {
|
|
||||||
const std::string& api_name = kSupportedAPIs[i];
|
|
||||||
if (api_name.find("Private") != std::string::npos) {
|
|
||||||
// Don't list private APIs.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t dot_pos = api_name.find('.');
|
|
||||||
if (dot_pos == std::string::npos) {
|
|
||||||
if (has_top_level_name) {
|
|
||||||
// End the previous top-level API entry.
|
|
||||||
html += "</ul></li>\n";
|
|
||||||
} else {
|
|
||||||
has_top_level_name = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a new top-level API entry.
|
|
||||||
html += "<li><a href=\"" + std::string(kDevURL) + api_name +
|
|
||||||
"\" target=\"new\">" + api_name + "</a><ul>\n";
|
|
||||||
} else {
|
|
||||||
// Function name.
|
|
||||||
const std::string& group_name = api_name.substr(0, dot_pos);
|
|
||||||
const std::string& function_name = api_name.substr(dot_pos + 1);
|
|
||||||
html += "\t<li><a href=\"" + std::string(kDevURL) + group_name +
|
|
||||||
"#method-" + function_name + "\" target=\"new\">" + api_name +
|
|
||||||
"</a></li>\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_top_level_name) {
|
|
||||||
// End the last top-level API entry.
|
|
||||||
html += "</ul></li>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
html += "</ul>\n</body>\n</html>";
|
|
||||||
|
|
||||||
action->mime_type = "text/html";
|
|
||||||
action->stream = CefStreamReader::CreateForData(
|
|
||||||
const_cast<char*>(html.c_str()), html.length());
|
|
||||||
action->stream_size = html.length();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnLicense(Action* action) {
|
|
||||||
base::StringPiece piece = CefContentClient::Get()->GetDataResource(
|
|
||||||
IDR_CEF_LICENSE_TXT, ui::SCALE_FACTOR_NONE);
|
|
||||||
if (piece.empty()) {
|
|
||||||
NOTREACHED() << "Failed to load license txt resource.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string html = "<html><head><title>License</title></head><body><pre>" +
|
|
||||||
piece.as_string() + "</pre></body></html>";
|
|
||||||
|
|
||||||
action->mime_type = "text/html";
|
|
||||||
action->stream = CefStreamReader::CreateForData(
|
|
||||||
const_cast<char*>(html.c_str()), html.length());
|
|
||||||
action->stream_size = html.length();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnVersion(CefRefPtr<CefBrowser> browser, Action* action) {
|
|
||||||
base::StringPiece piece = CefContentClient::Get()->GetDataResource(
|
|
||||||
IDR_CEF_VERSION_HTML, ui::SCALE_FACTOR_NONE);
|
|
||||||
if (piece.empty()) {
|
|
||||||
NOTREACHED() << "Failed to load version html resource.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateParser parser;
|
|
||||||
parser.Add("YEAR", MAKE_STRING(COPYRIGHT_YEAR));
|
|
||||||
parser.Add("CEF", CEF_VERSION);
|
|
||||||
parser.Add("CHROMIUM",
|
|
||||||
base::StringPrintf("%d.%d.%d.%d", CHROME_VERSION_MAJOR,
|
|
||||||
CHROME_VERSION_MINOR, CHROME_VERSION_BUILD,
|
|
||||||
CHROME_VERSION_PATCH));
|
|
||||||
parser.Add("OS", GetOSType());
|
|
||||||
parser.Add("WEBKIT", content::GetWebKitVersion());
|
|
||||||
parser.Add("JAVASCRIPT", v8::V8::GetVersion());
|
|
||||||
parser.Add("FLASH", std::string()); // Value populated asynchronously.
|
|
||||||
parser.Add("USERAGENT", CefContentClient::Get()->browser()->GetUserAgent());
|
|
||||||
parser.Add("COMMANDLINE", GetCommandLine());
|
|
||||||
parser.Add("MODULEPATH", GetModulePath());
|
|
||||||
parser.Add("CACHEPATH",
|
|
||||||
browser.get()
|
|
||||||
? browser->GetHost()->GetRequestContext()->GetCachePath()
|
|
||||||
: "");
|
|
||||||
|
|
||||||
std::string tmpl = piece.as_string();
|
|
||||||
parser.Parse(&tmpl);
|
|
||||||
|
|
||||||
action->mime_type = "text/html";
|
|
||||||
action->stream = CefStreamReader::CreateForData(
|
|
||||||
const_cast<char*>(tmpl.c_str()), tmpl.length());
|
|
||||||
action->stream_size = tmpl.length();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnWebUIHosts(Action* action) {
|
|
||||||
std::string html =
|
|
||||||
"<html>\n<head><title>WebUI Hosts</title></head>\n"
|
|
||||||
"<body bgcolor=\"white\"><h3>WebUI Hosts</h3>\n<ul>\n";
|
|
||||||
|
|
||||||
std::vector<std::string> list;
|
|
||||||
GetAllowedHosts(&list);
|
|
||||||
std::sort(list.begin(), list.end());
|
|
||||||
|
|
||||||
for (size_t i = 0U; i < list.size(); ++i) {
|
|
||||||
if (IsUnlistedHost(list[i]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
html += "<li><a href=\"chrome://" + list[i] + "\">chrome://" + list[i] +
|
|
||||||
"</a></li>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
list.clear();
|
|
||||||
GetDebugURLs(&list);
|
|
||||||
std::sort(list.begin(), list.end());
|
|
||||||
|
|
||||||
html +=
|
|
||||||
"</ul>\n<h3>For Debug</h3>\n"
|
|
||||||
"<p>The following pages are for debugging purposes only. Because they "
|
|
||||||
"crash or hang the renderer, they're not linked directly; you can type "
|
|
||||||
"them into the address bar if you need them.</p>\n<ul>\n";
|
|
||||||
for (size_t i = 0U; i < list.size(); ++i) {
|
|
||||||
html += "<li>" + std::string(list[i]) + "</li>\n";
|
|
||||||
}
|
|
||||||
html += "</ul>\n";
|
|
||||||
|
|
||||||
html += "</body>\n</html>";
|
|
||||||
|
|
||||||
action->mime_type = "text/html";
|
|
||||||
action->stream = CefStreamReader::CreateForData(
|
|
||||||
const_cast<char*>(html.c_str()), html.length());
|
|
||||||
action->stream_size = html.length();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void DidFinishChromeVersionLoad(CefRefPtr<CefFrame> frame) {
|
void DidFinishChromeVersionLoad(CefRefPtr<CefFrame> frame) {
|
||||||
// Retieve Flash version information and update asynchronously.
|
// Retieve Flash version information and update asynchronously.
|
||||||
class Visitor : public CefWebPluginInfoVisitor {
|
class Visitor : public CefWebPluginInfoVisitor {
|
||||||
@ -768,12 +829,6 @@ class ChromeProtocolHandlerWrapper
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void RegisterChromeHandler(CefURLRequestManager* request_manager) {
|
|
||||||
request_manager->AddFactory(
|
|
||||||
content::kChromeUIScheme, std::string(),
|
|
||||||
CreateInternalHandlerFactory(base::WrapUnique(new Delegate())));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterWebUIControllerFactory() {
|
void RegisterWebUIControllerFactory() {
|
||||||
// Channel all WebUI handling through CefWebUIControllerFactory.
|
// Channel all WebUI handling through CefWebUIControllerFactory.
|
||||||
content::WebUIControllerFactory::UnregisterFactoryForTesting(
|
content::WebUIControllerFactory::UnregisterFactoryForTesting(
|
||||||
@ -798,6 +853,10 @@ void DidFinishChromeLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) {
|
||||||
|
return CefWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(origin);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
|
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
|
||||||
WrapChromeProtocolHandler(
|
WrapChromeProtocolHandler(
|
||||||
CefURLRequestManager* request_manager,
|
CefURLRequestManager* request_manager,
|
||||||
|
@ -23,15 +23,16 @@ namespace content {
|
|||||||
class BrowserURLHandler;
|
class BrowserURLHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace url {
|
||||||
|
class Origin;
|
||||||
|
}
|
||||||
|
|
||||||
class CefURLRequestManager;
|
class CefURLRequestManager;
|
||||||
|
|
||||||
namespace scheme {
|
namespace scheme {
|
||||||
|
|
||||||
extern const char kChromeURL[];
|
extern const char kChromeURL[];
|
||||||
|
|
||||||
// Register the chrome scheme handler.
|
|
||||||
void RegisterChromeHandler(CefURLRequestManager* request_manager);
|
|
||||||
|
|
||||||
// Register the WebUI controller factory.
|
// Register the WebUI controller factory.
|
||||||
void RegisterWebUIControllerFactory();
|
void RegisterWebUIControllerFactory();
|
||||||
|
|
||||||
@ -41,6 +42,9 @@ void BrowserURLHandlerCreated(content::BrowserURLHandler* handler);
|
|||||||
// Used to fire any asynchronous content updates.
|
// Used to fire any asynchronous content updates.
|
||||||
void DidFinishChromeLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url);
|
void DidFinishChromeLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url);
|
||||||
|
|
||||||
|
// Returns true if WebUI is allowed to make network requests.
|
||||||
|
bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin);
|
||||||
|
|
||||||
// Create a new ProtocolHandler that will filter the URLs passed to the default
|
// Create a new ProtocolHandler that will filter the URLs passed to the default
|
||||||
// "chrome" protocol handler and forward the rest to CEF's handler.
|
// "chrome" protocol handler and forward the rest to CEF's handler.
|
||||||
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
|
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "libcef/browser/net/internal_scheme_handler.h"
|
#include "libcef/browser/net/internal_scheme_handler.h"
|
||||||
#include "libcef/browser/net/url_request_manager.h"
|
#include "libcef/browser/net/url_request_manager.h"
|
||||||
|
#include "libcef/browser/resource_context.h"
|
||||||
|
|
||||||
#include "base/memory/ptr_util.h"
|
#include "base/memory/ptr_util.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
@ -46,4 +47,10 @@ void RegisterChromeDevToolsHandler(CefURLRequestManager* request_manager) {
|
|||||||
CreateInternalHandlerFactory(base::WrapUnique(new Delegate())));
|
CreateInternalHandlerFactory(base::WrapUnique(new Delegate())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegisterChromeDevToolsHandler(CefResourceContext* resource_context) {
|
||||||
|
resource_context->RegisterSchemeHandlerFactory(
|
||||||
|
content::kChromeDevToolsScheme, kChromeDevToolsHost,
|
||||||
|
CreateInternalHandlerFactory(base::WrapUnique(new Delegate())));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace scheme
|
} // namespace scheme
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define CEF_LIBCEF_BROWSER_NET_DEVTOOLS_SCHEME_HANDLER_H_
|
#define CEF_LIBCEF_BROWSER_NET_DEVTOOLS_SCHEME_HANDLER_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
class CefResourceContext;
|
||||||
class CefURLRequestManager;
|
class CefURLRequestManager;
|
||||||
|
|
||||||
namespace scheme {
|
namespace scheme {
|
||||||
@ -14,6 +15,7 @@ extern const char kChromeDevToolsHost[];
|
|||||||
|
|
||||||
// Register the chrome-devtools scheme handler.
|
// Register the chrome-devtools scheme handler.
|
||||||
void RegisterChromeDevToolsHandler(CefURLRequestManager* request_manager);
|
void RegisterChromeDevToolsHandler(CefURLRequestManager* request_manager);
|
||||||
|
void RegisterChromeDevToolsHandler(CefResourceContext* resource_context);
|
||||||
|
|
||||||
} // namespace scheme
|
} // namespace scheme
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "libcef/browser/net/chrome_scheme_handler.h"
|
#include "libcef/browser/net/chrome_scheme_handler.h"
|
||||||
#include "libcef/browser/net/devtools_scheme_handler.h"
|
#include "libcef/browser/net/devtools_scheme_handler.h"
|
||||||
|
#include "libcef/browser/resource_context.h"
|
||||||
#include "libcef/common/net/scheme_registration.h"
|
#include "libcef/common/net/scheme_registration.h"
|
||||||
|
|
||||||
#include "base/memory/ptr_util.h"
|
#include "base/memory/ptr_util.h"
|
||||||
@ -72,10 +73,13 @@ void InstallInternalProtectedHandlers(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RegisterInternalHandlers(CefURLRequestManager* request_manager) {
|
void RegisterInternalHandlers(CefURLRequestManager* request_manager) {
|
||||||
scheme::RegisterChromeHandler(request_manager);
|
|
||||||
scheme::RegisterChromeDevToolsHandler(request_manager);
|
scheme::RegisterChromeDevToolsHandler(request_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegisterInternalHandlers(CefResourceContext* resource_context) {
|
||||||
|
scheme::RegisterChromeDevToolsHandler(resource_context);
|
||||||
|
}
|
||||||
|
|
||||||
void DidFinishLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url) {
|
void DidFinishLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url) {
|
||||||
if (validated_url.scheme() == content::kChromeUIScheme)
|
if (validated_url.scheme() == content::kChromeUIScheme)
|
||||||
scheme::DidFinishChromeLoad(frame, validated_url);
|
scheme::DidFinishChromeLoad(frame, validated_url);
|
||||||
|
@ -14,8 +14,9 @@
|
|||||||
namespace net {
|
namespace net {
|
||||||
class HostResolver;
|
class HostResolver;
|
||||||
class URLRequestJobFactoryImpl;
|
class URLRequestJobFactoryImpl;
|
||||||
}
|
} // namespace net
|
||||||
|
|
||||||
|
class CefResourceContext;
|
||||||
class CefURLRequestManager;
|
class CefURLRequestManager;
|
||||||
|
|
||||||
namespace scheme {
|
namespace scheme {
|
||||||
@ -30,6 +31,7 @@ void InstallInternalProtectedHandlers(
|
|||||||
|
|
||||||
// Register the internal scheme handlers that can be overridden.
|
// Register the internal scheme handlers that can be overridden.
|
||||||
void RegisterInternalHandlers(CefURLRequestManager* request_manager);
|
void RegisterInternalHandlers(CefURLRequestManager* request_manager);
|
||||||
|
void RegisterInternalHandlers(CefResourceContext* resource_context);
|
||||||
|
|
||||||
// Used to fire any asynchronous content updates.
|
// Used to fire any asynchronous content updates.
|
||||||
void DidFinishLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url);
|
void DidFinishLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url);
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
#include "libcef/browser/resource_context.h"
|
#include "libcef/browser/resource_context.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/net/scheme_handler.h"
|
||||||
#include "libcef/browser/net/url_request_context_getter.h"
|
#include "libcef/browser/net/url_request_context_getter.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
#include "libcef/common/net/scheme_registration.h"
|
#include "libcef/common/net/scheme_registration.h"
|
||||||
|
#include "libcef/common/net_service/util.h"
|
||||||
|
|
||||||
#include "base/i18n/case_conversion.h"
|
#include "base/i18n/case_conversion.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
@ -29,7 +31,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
CefResourceContext::CefResourceContext(bool is_off_the_record)
|
CefResourceContext::CefResourceContext(bool is_off_the_record)
|
||||||
: is_off_the_record_(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() {
|
CefResourceContext::~CefResourceContext() {
|
||||||
// This is normally called in the parent ResourceContext destructor, but we
|
// This is normally called in the parent ResourceContext destructor, but we
|
||||||
@ -187,6 +195,7 @@ void CefResourceContext::RegisterSchemeHandlerFactory(
|
|||||||
const std::string& domain_name,
|
const std::string& domain_name,
|
||||||
CefRefPtr<CefSchemeHandlerFactory> factory) {
|
CefRefPtr<CefSchemeHandlerFactory> factory) {
|
||||||
CEF_REQUIRE_IOT();
|
CEF_REQUIRE_IOT();
|
||||||
|
DCHECK(net_service::IsEnabled());
|
||||||
|
|
||||||
const std::string& scheme_lower = base::ToLowerASCII(scheme_name);
|
const std::string& scheme_lower = base::ToLowerASCII(scheme_name);
|
||||||
std::string domain_lower;
|
std::string domain_lower;
|
||||||
@ -213,12 +222,18 @@ void CefResourceContext::RegisterSchemeHandlerFactory(
|
|||||||
|
|
||||||
void CefResourceContext::ClearSchemeHandlerFactories() {
|
void CefResourceContext::ClearSchemeHandlerFactories() {
|
||||||
CEF_REQUIRE_IOT();
|
CEF_REQUIRE_IOT();
|
||||||
|
DCHECK(net_service::IsEnabled());
|
||||||
|
|
||||||
scheme_handler_factory_map_.clear();
|
scheme_handler_factory_map_.clear();
|
||||||
|
|
||||||
|
// Restore the default internal handlers.
|
||||||
|
scheme::RegisterInternalHandlers(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefSchemeHandlerFactory> CefResourceContext::GetSchemeHandlerFactory(
|
CefRefPtr<CefSchemeHandlerFactory> CefResourceContext::GetSchemeHandlerFactory(
|
||||||
const GURL& url) {
|
const GURL& url) {
|
||||||
CEF_REQUIRE_IOT();
|
CEF_REQUIRE_IOT();
|
||||||
|
DCHECK(net_service::IsEnabled());
|
||||||
|
|
||||||
if (scheme_handler_factory_map_.empty())
|
if (scheme_handler_factory_map_.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -246,3 +261,12 @@ CefRefPtr<CefSchemeHandlerFactory> CefResourceContext::GetSchemeHandlerFactory(
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefResourceContext::InitOnIOThread() {
|
||||||
|
CEF_REQUIRE_IOT();
|
||||||
|
|
||||||
|
if (net_service::IsEnabled()) {
|
||||||
|
// Add the default internal handlers.
|
||||||
|
scheme::RegisterInternalHandlers(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -88,6 +88,8 @@ class CefResourceContext : public content::ResourceContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void InitOnIOThread();
|
||||||
|
|
||||||
// Only accessed on the IO thread.
|
// Only accessed on the IO thread.
|
||||||
bool is_off_the_record_;
|
bool is_off_the_record_;
|
||||||
scoped_refptr<extensions::InfoMap> extension_info_map_;
|
scoped_refptr<extensions::InfoMap> extension_info_map_;
|
||||||
|
@ -123,16 +123,6 @@ class WebUITestHandler : public TestHandler {
|
|||||||
|
|
||||||
// Test hosts with special behaviors.
|
// Test hosts with special behaviors.
|
||||||
|
|
||||||
// Non-existing URLs should redirect to chrome://version/.
|
|
||||||
TEST(WebUITest, doesnotexist) {
|
|
||||||
UrlList url_list;
|
|
||||||
url_list.push_back("chrome://doesnotexist/");
|
|
||||||
CefRefPtr<WebUITestHandler> handler = new WebUITestHandler(url_list);
|
|
||||||
handler->set_expected_url("chrome://version/");
|
|
||||||
handler->ExecuteTest();
|
|
||||||
ReleaseAndWaitForDestructor(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// about:* URIs should redirect to chrome://*.
|
// about:* URIs should redirect to chrome://*.
|
||||||
TEST(WebUITest, about) {
|
TEST(WebUITest, about) {
|
||||||
UrlList url_list;
|
UrlList url_list;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user