Merge revision 1115 changes:

- Add CefApp::OnRegisterCustomSchemes callback to address url_util thread safety issues (issue #630).

git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1364@1116 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2013-03-04 20:18:59 +00:00
parent be0f78b229
commit cba0ef9b96
28 changed files with 583 additions and 256 deletions

View File

@ -728,6 +728,8 @@
'libcef/response_impl.cc',
'libcef/response_impl.h',
'libcef/scheme_impl.cc',
'libcef/scheme_registrar_impl.cc',
'libcef/scheme_registrar_impl.h',
'libcef/simple_clipboard_impl.cc',
'libcef/simple_clipboard_impl.h',
'libcef/sqlite_diagnostics_stub.cc',

View File

@ -180,6 +180,8 @@
'libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h',
'libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc',
'libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h',
'libcef_dll/cpptoc/scheme_registrar_cpptoc.cc',
'libcef_dll/cpptoc/scheme_registrar_cpptoc.h',
'libcef_dll/cpptoc/stream_reader_cpptoc.cc',
'libcef_dll/cpptoc/stream_reader_cpptoc.h',
'libcef_dll/cpptoc/stream_writer_cpptoc.cc',
@ -300,6 +302,8 @@
'libcef_dll/ctocpp/scheme_handler_callback_ctocpp.h',
'libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc',
'libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h',
'libcef_dll/ctocpp/scheme_registrar_ctocpp.cc',
'libcef_dll/ctocpp/scheme_registrar_ctocpp.h',
'libcef_dll/ctocpp/stream_reader_ctocpp.cc',
'libcef_dll/ctocpp/stream_reader_ctocpp.h',
'libcef_dll/ctocpp/stream_writer_ctocpp.cc',

View File

@ -103,6 +103,13 @@ typedef struct _cef_app_t {
///
cef_base_t base;
///
// Provides an opportunity to register custom schemes. Do not keep a reference
// to the |registrar| object. This function is called on the UI thread.
///
void (CEF_CALLBACK *on_register_custom_schemes)(struct _cef_app_t* self,
struct _cef_scheme_registrar_t* registrar);
///
// Return the handler for resource bundle events. If
// CefSettings.pack_loading_disabled is true (1) a handler must be returned.

View File

@ -45,53 +45,6 @@ extern "C" {
#include "include/capi/cef_base_capi.h"
///
// Register a custom scheme. This function should not be called for the built-in
// HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
//
// If |is_standard| is true (1) the scheme will be treated as a standard scheme.
// Standard schemes are subject to URL canonicalization and parsing rules as
// defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available
// at http://www.ietf.org/rfc/rfc1738.txt
//
// In particular, the syntax for standard scheme URLs must be of the form: <pre>
// [scheme]://[username]:[password]@[host]:[port]/[url-path]
// </pre> Standard scheme URLs must have a host component that is a fully
// qualified domain name as defined in Section 3.5 of RFC 1034 [13] and Section
// 2.1 of RFC 1123. These URLs will be canonicalized to "scheme://host/path" in
// the simplest case and "scheme://username:password@host:port/path" in the most
// explicit case. For example, "scheme:host/path" and "scheme:///host/path" will
// both be canonicalized to "scheme://host/path". The origin of a standard
// scheme URL is the combination of scheme, host and port (i.e.,
// "scheme://host:port" in the most explicit case).
//
// For non-standard scheme URLs only the "scheme:" component is parsed and
// canonicalized. The remainder of the URL will be passed to the handler as-is.
// For example, "scheme:///some%20text" will remain the same. Non-standard
// scheme URLs cannot be used as a target for form submission.
//
// If |is_local| is true (1) the scheme will be treated as local (i.e., with the
// same security rules as those applied to "file" URLs). Normal pages cannot
// link to or access local URLs. Also, by default, local URLs can only perform
// XMLHttpRequest calls to the same URL (origin + path) that originated the
// request. To allow XMLHttpRequest calls from a local URL to other URLs with
// the same origin set the CefSettings.file_access_from_file_urls_allowed value
// to true (1). To allow XMLHttpRequest calls from a local URL to all origins
// set the CefSettings.universal_access_from_file_urls_allowed value to true
// (1).
//
// If |is_display_isolated| is true (1) the scheme will be treated as display-
// isolated. This means that pages cannot display these URLs unless they are
// from the same scheme. For example, pages in another origin cannot create
// iframes or hyperlinks to URLs with this scheme.
//
// This function may be called on any thread. It should only be called once per
// unique |scheme_name| value. If |scheme_name| is already registered or if an
// error occurs this function will return false (0).
///
CEF_EXPORT int cef_register_custom_scheme(const cef_string_t* scheme_name,
int is_standard, int is_local, int is_display_isolated);
///
// Register a scheme handler factory for the specified |scheme_name| and
// optional |domain_name|. An NULL |domain_name| value for a standard scheme
@ -99,7 +52,7 @@ CEF_EXPORT int cef_register_custom_scheme(const cef_string_t* scheme_name,
// will be ignored for non-standard schemes. If |scheme_name| is a built-in
// scheme and no handler is returned by |factory| then the built-in scheme
// handler factory will be called. If |scheme_name| is a custom scheme the
// cef_register_custom_scheme() function should be called for that scheme. This
// CefRegisterCustomScheme() function should be called for that scheme. This
// function may be called multiple times to change or remove the factory that
// matches the specified |scheme_name| and optional |domain_name|. Returns false
// (0) if an error occurs. This function may be called on any thread.
@ -114,6 +67,67 @@ CEF_EXPORT int cef_register_scheme_handler_factory(
///
CEF_EXPORT int cef_clear_scheme_handler_factories();
///
// Structure that manages custom scheme registrations.
///
typedef struct _cef_scheme_registrar_t {
///
// Base structure.
///
cef_base_t base;
///
// Register a custom scheme. This function should not be called for the built-
// in HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
//
// If |is_standard| is true (1) the scheme will be treated as a standard
// scheme. Standard schemes are subject to URL canonicalization and parsing
// rules as defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1
// available at http://www.ietf.org/rfc/rfc1738.txt
//
// In particular, the syntax for standard scheme URLs must be of the form:
// <pre>
// [scheme]://[username]:[password]@[host]:[port]/[url-path]
// </pre> Standard scheme URLs must have a host component that is a fully
// qualified domain name as defined in Section 3.5 of RFC 1034 [13] and
// Section 2.1 of RFC 1123. These URLs will be canonicalized to
// "scheme://host/path" in the simplest case and
// "scheme://username:password@host:port/path" in the most explicit case. For
// example, "scheme:host/path" and "scheme:///host/path" will both be
// canonicalized to "scheme://host/path". The origin of a standard scheme URL
// is the combination of scheme, host and port (i.e., "scheme://host:port" in
// the most explicit case).
//
// For non-standard scheme URLs only the "scheme:" component is parsed and
// canonicalized. The remainder of the URL will be passed to the handler as-
// is. For example, "scheme:///some%20text" will remain the same. Non-standard
// scheme URLs cannot be used as a target for form submission.
//
// If |is_local| is true (1) the scheme will be treated as local (i.e., with
// the same security rules as those applied to "file" URLs). Normal pages
// cannot link to or access local URLs. Also, by default, local URLs can only
// perform XMLHttpRequest calls to the same URL (origin + path) that
// originated the request. To allow XMLHttpRequest calls from a local URL to
// other URLs with the same origin set the
// CefSettings.file_access_from_file_urls_allowed value to true (1). To allow
// XMLHttpRequest calls from a local URL to all origins set the
// CefSettings.universal_access_from_file_urls_allowed value to true (1).
//
// If |is_display_isolated| is true (1) the scheme will be treated as display-
// isolated. This means that pages cannot display these URLs unless they are
// from the same scheme. For example, pages in another origin cannot create
// iframes or hyperlinks to URLs with this scheme.
//
// This function may be called on any thread. It should only be called once
// per unique |scheme_name| value. If |scheme_name| is already registered or
// if an error occurs this function will return false (0).
///
int (CEF_CALLBACK *add_custom_scheme)(struct _cef_scheme_registrar_t* self,
const cef_string_t* scheme_name, int is_standard, int is_local,
int is_display_isolated);
} cef_scheme_registrar_t;
///
// Structure that creates cef_scheme_handler_t instances. The functions of this
// structure will always be called on the IO thread.

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
// Copyright (c) 2013 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@ -42,6 +42,7 @@
#include "include/cef_base.h"
#include "include/cef_proxy_handler.h"
#include "include/cef_resource_bundle_handler.h"
#include "include/cef_scheme.h"
class CefApp;
@ -105,6 +106,15 @@ void CefSetOSModalLoop(bool osModalLoop);
/*--cef(source=client,no_debugct_check)--*/
class CefApp : public virtual CefBase {
public:
///
// Provides an opportunity to register custom schemes. Do not keep a reference
// to the |registrar| object. This method is called on the UI thread.
///
/*--cef()--*/
virtual void OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) {
}
///
// Return the handler for resource bundle events. If
// CefSettings.pack_loading_disabled is true a handler must be returned. If no

View File

@ -46,57 +46,6 @@
class CefSchemeHandler;
class CefSchemeHandlerFactory;
///
// Register a custom scheme. This method should not be called for the built-in
// HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
//
// If |is_standard| is true the scheme will be treated as a standard scheme.
// Standard schemes are subject to URL canonicalization and parsing rules as
// defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available
// at http://www.ietf.org/rfc/rfc1738.txt
//
// In particular, the syntax for standard scheme URLs must be of the form:
// <pre>
// [scheme]://[username]:[password]@[host]:[port]/[url-path]
// </pre>
// Standard scheme URLs must have a host component that is a fully qualified
// domain name as defined in Section 3.5 of RFC 1034 [13] and Section 2.1 of RFC
// 1123. These URLs will be canonicalized to "scheme://host/path" in the
// simplest case and "scheme://username:password@host:port/path" in the most
// explicit case. For example, "scheme:host/path" and "scheme:///host/path" will
// both be canonicalized to "scheme://host/path". The origin of a standard
// scheme URL is the combination of scheme, host and port (i.e.,
// "scheme://host:port" in the most explicit case).
//
// For non-standard scheme URLs only the "scheme:" component is parsed and
// canonicalized. The remainder of the URL will be passed to the handler as-is.
// For example, "scheme:///some%20text" will remain the same. Non-standard
// scheme URLs cannot be used as a target for form submission.
//
// If |is_local| is true the scheme will be treated as local (i.e., with the
// same security rules as those applied to "file" URLs). Normal pages cannot
// link to or access local URLs. Also, by default, local URLs can only perform
// XMLHttpRequest calls to the same URL (origin + path) that originated the
// request. To allow XMLHttpRequest calls from a local URL to other URLs with
// the same origin set the CefSettings.file_access_from_file_urls_allowed value
// to true. To allow XMLHttpRequest calls from a local URL to all origins set
// the CefSettings.universal_access_from_file_urls_allowed value to true.
//
// If |is_display_isolated| is true the scheme will be treated as display-
// isolated. This means that pages cannot display these URLs unless they are
// from the same scheme. For example, pages in another origin cannot create
// iframes or hyperlinks to URLs with this scheme.
//
// This function may be called on any thread. It should only be called once
// per unique |scheme_name| value. If |scheme_name| is already registered or if
// an error occurs this method will return false.
///
/*--cef()--*/
bool CefRegisterCustomScheme(const CefString& scheme_name,
bool is_standard,
bool is_local,
bool is_display_isolated);
///
// Register a scheme handler factory for the specified |scheme_name| and
// optional |domain_name|. An empty |domain_name| value for a standard scheme
@ -122,6 +71,66 @@ bool CefRegisterSchemeHandlerFactory(const CefString& scheme_name,
bool CefClearSchemeHandlerFactories();
///
// Class that manages custom scheme registrations.
///
/*--cef(source=library)--*/
class CefSchemeRegistrar : public virtual CefBase {
public:
///
// Register a custom scheme. This method should not be called for the built-in
// HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
//
// If |is_standard| is true the scheme will be treated as a standard scheme.
// Standard schemes are subject to URL canonicalization and parsing rules as
// defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available
// at http://www.ietf.org/rfc/rfc1738.txt
//
// In particular, the syntax for standard scheme URLs must be of the form:
// <pre>
// [scheme]://[username]:[password]@[host]:[port]/[url-path]
// </pre>
// Standard scheme URLs must have a host component that is a fully qualified
// domain name as defined in Section 3.5 of RFC 1034 [13] and Section 2.1 of
// RFC 1123. These URLs will be canonicalized to "scheme://host/path" in the
// simplest case and "scheme://username:password@host:port/path" in the most
// explicit case. For example, "scheme:host/path" and "scheme:///host/path"
// will both be canonicalized to "scheme://host/path". The origin of a
// standard scheme URL is the combination of scheme, host and port (i.e.,
// "scheme://host:port" in the most explicit case).
//
// For non-standard scheme URLs only the "scheme:" component is parsed and
// canonicalized. The remainder of the URL will be passed to the handler
// as-is. For example, "scheme:///some%20text" will remain the same.
// Non-standard scheme URLs cannot be used as a target for form submission.
//
// If |is_local| is true the scheme will be treated as local (i.e., with the
// same security rules as those applied to "file" URLs). Normal pages cannot
// link to or access local URLs. Also, by default, local URLs can only perform
// XMLHttpRequest calls to the same URL (origin + path) that originated the
// request. To allow XMLHttpRequest calls from a local URL to other URLs with
// the same origin set the CefSettings.file_access_from_file_urls_allowed
// value to true. To allow XMLHttpRequest calls from a local URL to all
// origins set the CefSettings.universal_access_from_file_urls_allowed value
// to true.
//
// If |is_display_isolated| is true the scheme will be treated as display-
// isolated. This means that pages cannot display these URLs unless they are
// from the same scheme. For example, pages in another origin cannot create
// iframes or hyperlinks to URLs with this scheme.
//
// This function may be called on any thread. It should only be called once
// per unique |scheme_name| value. If |scheme_name| is already registered or
// if an error occurs this method will return false.
///
/*--cef()--*/
virtual bool AddCustomScheme(const CefString& scheme_name,
bool is_standard,
bool is_local,
bool is_display_isolated) =0;
};
///
// Class that creates CefSchemeHandler instances. The methods of this class will
// always be called on the IO thread.

View File

@ -125,9 +125,7 @@ class DevToolsSchemeHandlerFactory : public CefSchemeHandlerFactory {
} // namespace
// Register the DevTools scheme handler.
void RegisterDevToolsSchemeHandler(bool firstTime) {
if (firstTime)
CefRegisterCustomScheme(kChromeDevToolsScheme, true, false, true);
void RegisterDevToolsSchemeHandler() {
CefRegisterSchemeHandlerFactory(kChromeDevToolsScheme, kChromeDevToolsHost,
new DevToolsSchemeHandlerFactory());
}

View File

@ -11,6 +11,6 @@ extern const char kChromeDevToolsHost[];
extern const char kChromeDevToolsURL[];
// Register the DevTools scheme handler.
void RegisterDevToolsSchemeHandler(bool firstTime);
void RegisterDevToolsSchemeHandler();
#endif // CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_

View File

@ -281,7 +281,7 @@ bool CefContext::Initialize(const CefSettings& settings,
// Perform DevTools scheme registration when CEF initialization is complete.
CefThread::PostTask(CefThread::UI, FROM_HERE,
base::Bind(&RegisterDevToolsSchemeHandler, true));
base::Bind(&RegisterDevToolsSchemeHandler));
return true;
}

View File

@ -8,9 +8,11 @@
#include <string>
#include "include/cef_version.h"
#include "libcef/browser_devtools_scheme_handler.h"
#include "libcef/browser_webkit_glue.h"
#include "libcef/browser_webkit_init.h"
#include "libcef/cef_context.h"
#include "libcef/scheme_registrar_impl.h"
#include "libcef/v8_impl.h"
#include "base/bind.h"
@ -86,6 +88,20 @@ void CefProcessUIThread::Init() {
logging::DONT_LOCK_LOG_FILE, logging::APPEND_TO_OLD_LOG_FILE,
dcheck_state);
CefRefPtr<CefSchemeRegistrarImpl> schemeRegistrar(
new CefSchemeRegistrarImpl());
CefRefPtr<CefApp> app = _Context->application();
if (app.get())
app->OnRegisterCustomSchemes(schemeRegistrar.get());
// Add built-in schemes.
schemeRegistrar->AddCustomScheme(kChromeDevToolsScheme, true, false, true);
// No references to the registar should be kept.
schemeRegistrar->Detach();
DCHECK(schemeRegistrar->VerifyRefCount());
// Load ICU data tables.
bool ret = icu_util::Initialize();
if (!ret) {
@ -113,6 +129,9 @@ void CefProcessUIThread::Init() {
// Initialize WebKit encodings
webkit_glue::InitializeTextEncoding();
// Register custom schemes with WebKit.
schemeRegistrar->RegisterWithWebKit();
// Config the network module so it has access to a limited set of resources.
net::NetModule::SetResourceProvider(ResourceProvider);

View File

@ -53,13 +53,6 @@ bool IsStandardScheme(const std::string& scheme) {
return url_util::IsStandard(scheme.c_str(), scheme_comp);
}
void RegisterStandardScheme(const std::string& scheme) {
REQUIRE_UIT();
url_parse::Component scheme_comp(0, scheme.length());
if (!url_util::IsStandard(scheme.c_str(), scheme_comp))
url_util::AddStandardScheme(scheme.c_str());
}
// Copied from net/url_request/url_request_job_manager.cc.
struct SchemeToFactory {
const char* scheme;
@ -98,13 +91,6 @@ net::URLRequestJob* GetBuiltinSchemeRequestJob(
return NULL;
}
std::string ToLower(const std::string& str) {
std::string str_lower = str;
std::transform(str_lower.begin(), str_lower.end(), str_lower.begin(),
towlower);
return str;
}
bool SetHeaderIfMissing(CefRequest::HeaderMap& headerMap,
const std::string& name,
const std::string& value) {
@ -614,8 +600,8 @@ class CefUrlRequestManager {
REQUIRE_IOT();
std::string scheme_lower = ToLower(scheme);
std::string domain_lower = ToLower(domain);
std::string scheme_lower = StringToLowerASCII(scheme);
std::string domain_lower = StringToLowerASCII(domain);
// Hostname is only supported for standard schemes.
if (!IsStandardScheme(scheme_lower))
@ -637,8 +623,8 @@ class CefUrlRequestManager {
const std::string& domain) {
REQUIRE_IOT();
std::string scheme_lower = ToLower(scheme);
std::string domain_lower = ToLower(domain);
std::string scheme_lower = StringToLowerASCII(scheme);
std::string domain_lower = StringToLowerASCII(domain);
// Hostname is only supported for standard schemes.
if (!IsStandardScheme(scheme_lower))
@ -672,50 +658,6 @@ class CefUrlRequestManager {
handler_map_.clear();
}
// Check if a scheme has already been registered.
bool HasRegisteredScheme(const std::string& scheme) {
std::string scheme_lower = ToLower(scheme);
// Don't register builtin schemes.
if (IsBuiltinScheme(scheme_lower))
return true;
scheme_set_lock_.Acquire();
bool registered = (scheme_set_.find(scheme_lower) != scheme_set_.end());
scheme_set_lock_.Release();
return registered;
}
// Register a scheme.
bool RegisterScheme(const std::string& scheme,
bool is_standard,
bool is_local,
bool is_display_isolated) {
if (HasRegisteredScheme(scheme)) {
NOTREACHED() << "Scheme already registered: " << scheme;
return false;
}
std::string scheme_lower = ToLower(scheme);
scheme_set_lock_.Acquire();
scheme_set_.insert(scheme_lower);
scheme_set_lock_.Release();
if (is_standard)
RegisterStandardScheme(scheme_lower);
if (is_local) {
WebSecurityPolicy::registerURLSchemeAsLocal(
WebString::fromUTF8(scheme_lower));
}
if (is_display_isolated) {
WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(
WebString::fromUTF8(scheme_lower));
}
return true;
}
private:
// Retrieve the matching handler factory, if any. |scheme| will already be in
// lower case.
@ -799,34 +741,6 @@ CefUrlRequestManager* CefUrlRequestManager::GetInstance() {
} // namespace
bool CefRegisterCustomScheme(const CefString& scheme_name,
bool is_standard,
bool is_local,
bool is_display_isolated) {
// Verify that the context is in a valid state.
if (!CONTEXT_STATE_VALID()) {
NOTREACHED() << "context not valid";
return false;
}
if (CefThread::CurrentlyOn(CefThread::UI)) {
// Must be executed on the UI thread because it calls WebKit APIs.
return CefUrlRequestManager::GetInstance()->RegisterScheme(scheme_name,
is_standard, is_local, is_display_isolated);
} else {
// Verify that the scheme has not already been registered.
if (CefUrlRequestManager::GetInstance()->HasRegisteredScheme(scheme_name)) {
NOTREACHED() << "Scheme already registered: " << scheme_name;
return false;
}
CefThread::PostTask(CefThread::UI, FROM_HERE,
base::Bind(base::IgnoreResult(&CefRegisterCustomScheme), scheme_name,
is_standard, is_local, is_display_isolated));
return true;
}
}
bool CefRegisterSchemeHandlerFactory(
const CefString& scheme_name,
const CefString& domain_name,
@ -860,7 +774,7 @@ bool CefClearSchemeHandlerFactories() {
CefUrlRequestManager::GetInstance()->ClearFactories();
// Re-register the DevTools scheme handler.
RegisterDevToolsSchemeHandler(false);
RegisterDevToolsSchemeHandler();
} else {
CefThread::PostTask(CefThread::IO, FROM_HERE,
base::Bind(base::IgnoreResult(&CefClearSchemeHandlerFactories)));

View File

@ -0,0 +1,83 @@
// 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/scheme_registrar_impl.h"
#include <string>
#include "base/logging.h"
#include "base/string_util.h"
#include "googleurl/src/url_util.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
struct CefSchemeRegistrarImpl::SchemeInfo {
std::string scheme_name;
bool is_local;
bool is_display_isolated;
};
CefSchemeRegistrarImpl::CefSchemeRegistrarImpl()
: supported_thread_id_(base::PlatformThread::CurrentId()) {
}
bool CefSchemeRegistrarImpl::AddCustomScheme(
const CefString& scheme_name,
bool is_standard,
bool is_local,
bool is_display_isolated) {
if (!VerifyContext())
return false;
std::string scheme_lower = StringToLowerASCII(scheme_name.ToString());
if (is_standard) {
url_parse::Component scheme_comp(0, scheme_lower.length());
if (!url_util::IsStandard(scheme_lower.c_str(), scheme_comp))
url_util::AddStandardScheme(scheme_lower.c_str());
}
SchemeInfo info = {scheme_lower, is_local, is_display_isolated};
scheme_info_list_.push_back(info);
return true;
}
void CefSchemeRegistrarImpl::RegisterWithWebKit() {
if (scheme_info_list_.empty())
return;
// Register the custom schemes.
SchemeInfoList::const_iterator it = scheme_info_list_.begin();
for (; it != scheme_info_list_.end(); ++it) {
const SchemeInfo& info = *it;
if (info.is_local) {
WebKit::WebSecurityPolicy::registerURLSchemeAsLocal(
WebKit::WebString::fromUTF8(info.scheme_name));
}
if (info.is_display_isolated) {
WebKit::WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(
WebKit::WebString::fromUTF8(info.scheme_name));
}
}
}
bool CefSchemeRegistrarImpl::VerifyRefCount() {
return (GetRefCt() == 1);
}
void CefSchemeRegistrarImpl::Detach() {
DCHECK_EQ(base::PlatformThread::CurrentId(), supported_thread_id_);
url_util::LockStandardSchemes();
supported_thread_id_ = base::kInvalidThreadId;
}
bool CefSchemeRegistrarImpl::VerifyContext() {
if (base::PlatformThread::CurrentId() != supported_thread_id_) {
// This object should only be accessed from the thread that created it.
NOTREACHED();
return false;
}
return true;
}

View File

@ -0,0 +1,49 @@
// 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.
#ifndef CEF_LIBCEF_SCHEME_REGISTRAR_IMPL_H_
#define CEF_LIBCEF_SCHEME_REGISTRAR_IMPL_H_
#pragma once
#include <list>
#include <string>
#include "include/cef_scheme.h"
#include "base/threading/platform_thread.h"
class CefSchemeRegistrarImpl : public CefSchemeRegistrar {
public:
CefSchemeRegistrarImpl();
// CefSchemeRegistrar methods.
virtual bool AddCustomScheme(const CefString& scheme_name,
bool is_standard,
bool is_local,
bool is_display_isolated) OVERRIDE;
void RegisterWithWebKit();
// Verify that only a single reference exists to all CefSchemeRegistrarImpl
// objects.
bool VerifyRefCount();
void Detach();
private:
// Verify that the object is being accessed from the correct thread.
bool VerifyContext();
base::PlatformThreadId supported_thread_id_;
// Custom schemes that need to be registered with WebKit.
struct SchemeInfo;
typedef std::list<SchemeInfo> SchemeInfoList;
SchemeInfoList scheme_info_list_;
IMPLEMENT_REFCOUNTING(CefSchemeRegistrarImpl);
DISALLOW_COPY_AND_ASSIGN(CefSchemeRegistrarImpl);
};
#endif // CEF_LIBCEF_SCHEME_REGISTRAR_IMPL_H_

View File

@ -13,10 +13,28 @@
#include "libcef_dll/cpptoc/app_cpptoc.h"
#include "libcef_dll/cpptoc/proxy_handler_cpptoc.h"
#include "libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h"
#include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h"
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK app_on_register_custom_schemes(struct _cef_app_t* self,
struct _cef_scheme_registrar_t* registrar) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: registrar; type: refptr_diff
DCHECK(registrar);
if (!registrar)
return;
// Execute
CefAppCppToC::Get(self)->OnRegisterCustomSchemes(
CefSchemeRegistrarCToCpp::Wrap(registrar));
}
struct _cef_resource_bundle_handler_t* CEF_CALLBACK app_get_resource_bundle_handler(
struct _cef_app_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -54,6 +72,7 @@ struct _cef_proxy_handler_t* CEF_CALLBACK app_get_proxy_handler(
CefAppCppToC::CefAppCppToC(CefApp* cls)
: CefCppToC<CefAppCppToC, CefApp, cef_app_t>(cls) {
struct_.struct_.on_register_custom_schemes = app_on_register_custom_schemes;
struct_.struct_.get_resource_bundle_handler = app_get_resource_bundle_handler;
struct_.struct_.get_proxy_handler = app_get_proxy_handler;
}

View File

@ -0,0 +1,55 @@
// 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h"
// MEMBER FUNCTIONS - Body may be edited by hand.
int CEF_CALLBACK scheme_registrar_add_custom_scheme(
struct _cef_scheme_registrar_t* self, const cef_string_t* scheme_name,
int is_standard, int is_local, int is_display_isolated) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: scheme_name; type: string_byref_const
DCHECK(scheme_name);
if (!scheme_name)
return 0;
// Execute
bool _retval = CefSchemeRegistrarCppToC::Get(self)->AddCustomScheme(
CefString(scheme_name),
is_standard?true:false,
is_local?true:false,
is_display_isolated?true:false);
// Return type: bool
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
CefSchemeRegistrarCppToC::CefSchemeRegistrarCppToC(CefSchemeRegistrar* cls)
: CefCppToC<CefSchemeRegistrarCppToC, CefSchemeRegistrar,
cef_scheme_registrar_t>(cls) {
struct_.struct_.add_custom_scheme = scheme_registrar_add_custom_scheme;
}
#ifndef NDEBUG
template<> long CefCppToC<CefSchemeRegistrarCppToC, CefSchemeRegistrar,
cef_scheme_registrar_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,37 @@
// 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_SCHEME_REGISTRAR_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_SCHEME_REGISTRAR_CPPTOC_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef_scheme.h"
#include "include/capi/cef_scheme_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed DLL-side only.
class CefSchemeRegistrarCppToC
: public CefCppToC<CefSchemeRegistrarCppToC, CefSchemeRegistrar,
cef_scheme_registrar_t> {
public:
explicit CefSchemeRegistrarCppToC(CefSchemeRegistrar* cls);
virtual ~CefSchemeRegistrarCppToC() {}
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_SCHEME_REGISTRAR_CPPTOC_H_

View File

@ -10,6 +10,7 @@
// for more information.
//
#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h"
#include "libcef_dll/ctocpp/app_ctocpp.h"
#include "libcef_dll/ctocpp/proxy_handler_ctocpp.h"
#include "libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h"
@ -17,6 +18,23 @@
// VIRTUAL METHODS - Body may be edited by hand.
void CefAppCToCpp::OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) {
if (CEF_MEMBER_MISSING(struct_, on_register_custom_schemes))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: registrar; type: refptr_diff
DCHECK(registrar.get());
if (!registrar.get())
return;
// Execute
struct_->on_register_custom_schemes(struct_,
CefSchemeRegistrarCppToC::Wrap(registrar));
}
CefRefPtr<CefResourceBundleHandler> CefAppCToCpp::GetResourceBundleHandler() {
if (CEF_MEMBER_MISSING(struct_, get_resource_bundle_handler))
return NULL;

View File

@ -32,6 +32,8 @@ class CefAppCToCpp
virtual ~CefAppCToCpp() {}
// CefApp methods
virtual void OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE;
virtual CefRefPtr<CefResourceBundleHandler> GetResourceBundleHandler(
) OVERRIDE;
virtual CefRefPtr<CefProxyHandler> GetProxyHandler() OVERRIDE;

View File

@ -0,0 +1,46 @@
// 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h"
// VIRTUAL METHODS - Body may be edited by hand.
bool CefSchemeRegistrarCToCpp::AddCustomScheme(const CefString& scheme_name,
bool is_standard, bool is_local, bool is_display_isolated) {
if (CEF_MEMBER_MISSING(struct_, add_custom_scheme))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: scheme_name; type: string_byref_const
DCHECK(!scheme_name.empty());
if (scheme_name.empty())
return false;
// Execute
int _retval = struct_->add_custom_scheme(struct_,
scheme_name.GetStruct(),
is_standard,
is_local,
is_display_isolated);
// Return type: bool
return _retval?true:false;
}
#ifndef NDEBUG
template<> long CefCToCpp<CefSchemeRegistrarCToCpp, CefSchemeRegistrar,
cef_scheme_registrar_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,43 @@
// 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef_scheme.h"
#include "include/capi/cef_scheme_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed wrapper-side only.
class CefSchemeRegistrarCToCpp
: public CefCToCpp<CefSchemeRegistrarCToCpp, CefSchemeRegistrar,
cef_scheme_registrar_t> {
public:
explicit CefSchemeRegistrarCToCpp(cef_scheme_registrar_t* str)
: CefCToCpp<CefSchemeRegistrarCToCpp, CefSchemeRegistrar,
cef_scheme_registrar_t>(str) {}
virtual ~CefSchemeRegistrarCToCpp() {}
// CefSchemeRegistrar methods
virtual bool AddCustomScheme(const CefString& scheme_name, bool is_standard,
bool is_local, bool is_display_isolated) OVERRIDE;
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_

View File

@ -39,6 +39,7 @@
#include "libcef_dll/cpptoc/request_cpptoc.h"
#include "libcef_dll/cpptoc/response_cpptoc.h"
#include "libcef_dll/cpptoc/scheme_handler_callback_cpptoc.h"
#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h"
#include "libcef_dll/cpptoc/stream_reader_cpptoc.h"
#include "libcef_dll/cpptoc/stream_writer_cpptoc.h"
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
@ -157,6 +158,7 @@ CEF_EXPORT void cef_shutdown() {
DCHECK_EQ(CefSchemeHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefSchemeHandlerCallbackCppToC::DebugObjCt, 0);
DCHECK_EQ(CefSchemeHandlerFactoryCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefSchemeRegistrarCppToC::DebugObjCt, 0);
DCHECK_EQ(CefStreamReaderCppToC::DebugObjCt, 0);
DCHECK_EQ(CefStreamWriterCppToC::DebugObjCt, 0);
DCHECK_EQ(CefTaskCToCpp::DebugObjCt, 0);
@ -286,26 +288,6 @@ CEF_EXPORT int cef_clear_cross_origin_whitelist() {
return _retval;
}
CEF_EXPORT int cef_register_custom_scheme(const cef_string_t* scheme_name,
int is_standard, int is_local, int is_display_isolated) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: scheme_name; type: string_byref_const
DCHECK(scheme_name);
if (!scheme_name)
return 0;
// Execute
bool _retval = CefRegisterCustomScheme(
CefString(scheme_name),
is_standard?true:false,
is_local?true:false,
is_display_isolated?true:false);
// Return type: bool
return _retval;
}
CEF_EXPORT int cef_register_scheme_handler_factory(
const cef_string_t* scheme_name, const cef_string_t* domain_name,
struct _cef_scheme_handler_factory_t* factory) {

View File

@ -73,6 +73,7 @@
#include "libcef_dll/ctocpp/request_ctocpp.h"
#include "libcef_dll/ctocpp/response_ctocpp.h"
#include "libcef_dll/ctocpp/scheme_handler_callback_ctocpp.h"
#include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h"
#include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
#include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
@ -159,6 +160,7 @@ CEF_GLOBAL void CefShutdown() {
DCHECK_EQ(CefSchemeHandlerCallbackCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefSchemeHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefSchemeHandlerFactoryCppToC::DebugObjCt, 0);
DCHECK_EQ(CefSchemeRegistrarCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefStreamReaderCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefStreamWriterCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefTaskCppToC::DebugObjCt, 0);
@ -288,26 +290,6 @@ CEF_GLOBAL bool CefClearCrossOriginWhitelist() {
return _retval?true:false;
}
CEF_GLOBAL bool CefRegisterCustomScheme(const CefString& scheme_name,
bool is_standard, bool is_local, bool is_display_isolated) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: scheme_name; type: string_byref_const
DCHECK(!scheme_name.empty());
if (scheme_name.empty())
return false;
// Execute
int _retval = cef_register_custom_scheme(
scheme_name.GetStruct(),
is_standard,
is_local,
is_display_isolated);
// Return type: bool
return _retval?true:false;
}
CEF_GLOBAL bool CefRegisterSchemeHandlerFactory(const CefString& scheme_name,
const CefString& domain_name,
CefRefPtr<CefSchemeHandlerFactory> factory) {

View File

@ -17,6 +17,7 @@
#include "cefclient/cefclient_switches.h"
#include "cefclient/client_handler.h"
#include "cefclient/binding_test.h"
#include "cefclient/scheme_test.h"
#include "cefclient/string_util.h"
#include "cefclient/util.h"
@ -125,6 +126,11 @@ class ClientApp : public CefApp,
proxy_config_(proxy_config) {
}
virtual void OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE {
AddSchemeTestSchemes(registrar);
}
// CefApp methods
virtual CefRefPtr<CefProxyHandler> GetProxyHandler() OVERRIDE { return this; }

View File

@ -157,8 +157,11 @@ class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
};
void AddSchemeTestSchemes(CefRefPtr<CefSchemeRegistrar> registrar) {
registrar->AddCustomScheme("client", true, false, false);
}
void InitSchemeTest() {
CefRegisterCustomScheme("client", true, false, false);
CefRegisterSchemeHandlerFactory("client", "tests",
new ClientSchemeHandlerFactory());
}

View File

@ -6,9 +6,10 @@
#define CEF_TESTS_CEFCLIENT_SCHEME_TEST_H_
#pragma once
#include "include/cef_base.h"
#include "include/cef_browser.h"
#include "include/cef_scheme.h"
class CefBrowser;
void AddSchemeTestSchemes(CefRefPtr<CefSchemeRegistrar> registrar);
// Register the scheme handler.
void InitSchemeTest();

View File

@ -808,8 +808,6 @@ class CookieTestSchemeHandler : public TestHandler {
manager2_ = CefCookieManager::CreateManager(CefString());
if (scheme_ != "http") {
CefRegisterCustomScheme(scheme_, true, false, false);
std::vector<CefString> schemes;
schemes.push_back("http");
schemes.push_back("https");
@ -952,3 +950,12 @@ TEST(CookieTest, GetCookieManagerCustom) {
EXPECT_TRUE(handler->got_cookie2_);
EXPECT_TRUE(handler->got_cookie3_);
}
// Entry point for registering custom schemes.
// Called from run_all_unittests.cc.
void RegisterCookieCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) {
// Used by the GetCookieManagerCustom test.
registrar->AddCustomScheme("ccustom", true, false, false);
}

View File

@ -40,6 +40,27 @@ class CefTestThread : public base::Thread {
int retval_;
};
class ClientApp : public CefApp {
public:
ClientApp() {}
virtual void OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE {
// Bring in the scheme handler tests.
extern void RegisterSchemeHandlerCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar);
RegisterSchemeHandlerCustomSchemes(registrar);
// Bring in the cookie tests.
extern void RegisterCookieCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar);
RegisterCookieCustomSchemes(registrar);
}
protected:
IMPLEMENT_REFCOUNTING(ClientApp);
};
} // namespace
@ -57,7 +78,7 @@ int main(int argc, char** argv) {
#endif
// Initialize CEF.
CefInitialize(settings, NULL);
CefInitialize(settings, new ClientApp());
// Create the test suite object.
CefTestSuite test_suite(argc, argv);

View File

@ -337,20 +337,6 @@ TestResults g_TestResults;
// If |domain| is empty the scheme will be registered as non-standard.
void RegisterTestScheme(const std::string& scheme, const std::string& domain) {
g_TestResults.reset();
static std::set<std::string> schemes;
if (schemes.empty()) {
// Never register built-in schemes.
schemes.insert("http");
}
// Only register custom schemes one time.
if (schemes.find(scheme) == schemes.end()) {
EXPECT_TRUE(CefRegisterCustomScheme(scheme, domain.empty()?false:true,
false, false));
WaitForUIThread();
schemes.insert(scheme);
}
EXPECT_TRUE(CefRegisterSchemeHandlerFactory(scheme, domain,
new ClientSchemeHandlerFactory(&g_TestResults)));
@ -973,3 +959,13 @@ TEST(SchemeHandlerTest, HttpXSSDifferentOriginWithDomain) {
ClearTestSchemes();
}
// Entry point for registering custom schemes.
// Called from run_all_unittests.cc.
void RegisterSchemeHandlerCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) {
// Add a custom standard scheme.
registrar->AddCustomScheme("customstd", true, false, false);
// Ad a custom non-standard scheme.
registrar->AddCustomScheme("customnonstd", false, false, false);
}