mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-03 04:27:43 +01:00
Improvements to scheme handling (issue #246).
- Break CefRegisterScheme into separate CefRegisterCustomScheme and CefRegisterSchemeHandlerFactory functions. - Allow registration of handlers for built-in schemes. - Supply scheme and request information to CefSchemeHandlerFactory::Create. - Add CrossOriginWhitelist functions for bypassing the same-origin policy with both built-in and custom standard schemes. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@247 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
42b5597214
commit
63aa102a6a
1
cef.gyp
1
cef.gyp
@ -696,6 +696,7 @@
|
||||
'libcef/external_protocol_handler.h',
|
||||
'libcef/http_header_utils.cc',
|
||||
'libcef/http_header_utils.h',
|
||||
'libcef/origin_whitelist_impl.cc',
|
||||
'libcef/request_impl.cc',
|
||||
'libcef/request_impl.h',
|
||||
'libcef/response_impl.cc',
|
||||
|
@ -172,8 +172,10 @@ bool CefRegisterExtension(const CefString& extension_name,
|
||||
const CefString& javascript_code,
|
||||
CefRefPtr<CefV8Handler> handler);
|
||||
|
||||
// CEF supports two types of schemes, standard and non-standard.
|
||||
// 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
|
||||
@ -194,17 +196,87 @@ bool CefRegisterExtension(const CefString& extension_name,
|
||||
// For example, "scheme:///some%20text" will remain the same. Non-standard
|
||||
// scheme URLs cannot be used as a target for form submission.
|
||||
//
|
||||
// Register a custom scheme handler factory for the specified |scheme_name| and
|
||||
// optional |host_name|. Specifying an empty |host_name| value for standard
|
||||
// schemes will match all host names. The |host_name| value will be ignored for
|
||||
// non-standard schemes. Set |is_standard| to true to register as a standard
|
||||
// scheme or false to register a non-standard scheme. This function may be
|
||||
// called on any thread.
|
||||
// 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). This means that normal
|
||||
// pages cannot link to or access URLs of this scheme.
|
||||
//
|
||||
// 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 CefRegisterScheme(const CefString& scheme_name,
|
||||
const CefString& host_name,
|
||||
bool is_standard,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory);
|
||||
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
|
||||
// will cause the factory to match all domain names. The |domain_name| value
|
||||
// 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
|
||||
// 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 if an error occurs. This function may be called on any thread.
|
||||
/*--cef()--*/
|
||||
bool CefRegisterSchemeHandlerFactory(const CefString& scheme_name,
|
||||
const CefString& domain_name,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory);
|
||||
|
||||
// Clear all registered scheme handler factories. Returns false on error. This
|
||||
// function may be called on any thread.
|
||||
/*--cef()--*/
|
||||
bool CefClearSchemeHandlerFactories();
|
||||
|
||||
// Add an entry to the cross-origin access whitelist.
|
||||
//
|
||||
// The same-origin policy restricts how scripts hosted from different origins
|
||||
// (scheme + domain) can communicate. By default, scripts can only access
|
||||
// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes
|
||||
// (but no other schemes) can use the "Access-Control-Allow-Origin" header to
|
||||
// allow cross-origin requests. For example, https://source.example.com can make
|
||||
// XMLHttpRequest requests on http://target.example.com if the
|
||||
// http://target.example.com request returns an "Access-Control-Allow-Origin:
|
||||
// https://source.example.com" response header.
|
||||
//
|
||||
// Scripts in separate frames or iframes and hosted from the same protocol and
|
||||
// domain suffix can execute cross-origin JavaScript if both pages set the
|
||||
// document.domain value to the same domain suffix. For example,
|
||||
// scheme://foo.example.com and scheme://bar.example.com can communicate using
|
||||
// JavaScript if both domains set document.domain="example.com".
|
||||
//
|
||||
// This method is used to allow access to origins that would otherwise violate
|
||||
// the same-origin policy. Scripts hosted underneath the fully qualified
|
||||
// |source_origin| URL (like http://www.example.com) will be allowed access to
|
||||
// all resources hosted on the specified |target_protocol| and |target_domain|.
|
||||
// If |allow_target_subdomains| is true access will also be allowed to all
|
||||
// subdomains of the target domain. This function may be called on any thread.
|
||||
// Returns false if |source_origin| is invalid or the whitelist cannot be
|
||||
// accessed.
|
||||
/*--cef()--*/
|
||||
bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin,
|
||||
const CefString& target_protocol,
|
||||
const CefString& target_domain,
|
||||
bool allow_target_subdomains);
|
||||
|
||||
// Remove an entry from the cross-origin access whitelist. Returns false if
|
||||
// |source_origin| is invalid or the whitelist cannot be accessed.
|
||||
/*--cef()--*/
|
||||
bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin,
|
||||
const CefString& target_protocol,
|
||||
const CefString& target_domain,
|
||||
bool allow_target_subdomains);
|
||||
|
||||
// Remove all entries from the cross-origin access whitelist. Returns false if
|
||||
// the whitelist cannot be accessed.
|
||||
/*--cef()--*/
|
||||
bool CefClearCrossOriginWhitelist();
|
||||
|
||||
typedef cef_thread_id_t CefThreadId;
|
||||
|
||||
@ -1744,7 +1816,8 @@ class CefSchemeHandlerFactory : public virtual CefBase
|
||||
public:
|
||||
// Return a new scheme handler instance to handle the request.
|
||||
/*--cef()--*/
|
||||
virtual CefRefPtr<CefSchemeHandler> Create() =0;
|
||||
virtual CefRefPtr<CefSchemeHandler> Create(const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request) =0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -133,8 +133,10 @@ CEF_EXPORT void cef_run_message_loop();
|
||||
CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name,
|
||||
const cef_string_t* javascript_code, struct _cef_v8handler_t* handler);
|
||||
|
||||
// CEF supports two types of schemes, standard and non-standard.
|
||||
// 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
|
||||
@ -155,16 +157,78 @@ CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name,
|
||||
// For example, "scheme:///some%20text" will remain the same. Non-standard
|
||||
// scheme URLs cannot be used as a target for form submission.
|
||||
//
|
||||
// Register a custom scheme handler factory for the specified |scheme_name| and
|
||||
// optional |host_name|. Specifying an NULL |host_name| value for standard
|
||||
// schemes will match all host names. The |host_name| value will be ignored for
|
||||
// non-standard schemes. Set |is_standard| to true (1) to register as a standard
|
||||
// scheme or false (0) to register a non-standard scheme. This function may be
|
||||
// called on any thread.
|
||||
CEF_EXPORT int cef_register_scheme(const cef_string_t* scheme_name,
|
||||
const cef_string_t* host_name, int is_standard,
|
||||
// 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). This means that normal
|
||||
// pages cannot link to or access URLs of this scheme.
|
||||
//
|
||||
// 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
|
||||
// will cause the factory to match all domain names. The |domain_name| value
|
||||
// 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
|
||||
// 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.
|
||||
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);
|
||||
|
||||
// Clear all registered scheme handler factories. Returns false (0) on error.
|
||||
// This function may be called on any thread.
|
||||
CEF_EXPORT int cef_clear_scheme_handler_factories();
|
||||
|
||||
// Add an entry to the cross-origin access whitelist.
|
||||
//
|
||||
// The same-origin policy restricts how scripts hosted from different origins
|
||||
// (scheme + domain) can communicate. By default, scripts can only access
|
||||
// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes
|
||||
// (but no other schemes) can use the "Access-Control-Allow-Origin" header to
|
||||
// allow cross-origin requests. For example, https://source.example.com can make
|
||||
// XMLHttpRequest requests on http://target.example.com if the
|
||||
// http://target.example.com request returns an "Access-Control-Allow-Origin:
|
||||
// https://source.example.com" response header.
|
||||
//
|
||||
// Scripts in separate frames or iframes and hosted from the same protocol and
|
||||
// domain suffix can execute cross-origin JavaScript if both pages set the
|
||||
// document.domain value to the same domain suffix. For example,
|
||||
// scheme://foo.example.com and scheme://bar.example.com can communicate using
|
||||
// JavaScript if both domains set document.domain="example.com".
|
||||
//
|
||||
// This function is used to allow access to origins that would otherwise violate
|
||||
// the same-origin policy. Scripts hosted underneath the fully qualified
|
||||
// |source_origin| URL (like http://www.example.com) will be allowed access to
|
||||
// all resources hosted on the specified |target_protocol| and |target_domain|.
|
||||
// If |allow_target_subdomains| is true (1) access will also be allowed to all
|
||||
// subdomains of the target domain. This function may be called on any thread.
|
||||
// Returns false (0) if |source_origin| is invalid or the whitelist cannot be
|
||||
// accessed.
|
||||
CEF_EXPORT int cef_add_cross_origin_whitelist_entry(
|
||||
const cef_string_t* source_origin, const cef_string_t* target_protocol,
|
||||
const cef_string_t* target_domain, int allow_target_subdomains);
|
||||
|
||||
// Remove an entry from the cross-origin access whitelist. Returns false (0) if
|
||||
// |source_origin| is invalid or the whitelist cannot be accessed.
|
||||
CEF_EXPORT int cef_remove_cross_origin_whitelist_entry(
|
||||
const cef_string_t* source_origin, const cef_string_t* target_protocol,
|
||||
const cef_string_t* target_domain, int allow_target_subdomains);
|
||||
|
||||
// Remove all entries from the cross-origin access whitelist. Returns false (0)
|
||||
// if the whitelist cannot be accessed.
|
||||
CEF_EXPORT int cef_clear_cross_origin_whitelist();
|
||||
|
||||
// CEF maintains multiple internal threads that are used for handling different
|
||||
// types of tasks. The UI thread creates the browser window and is used for all
|
||||
// interaction with the WebKit rendering engine and V8 JavaScript engine (The UI
|
||||
@ -1539,7 +1603,8 @@ typedef struct _cef_scheme_handler_factory_t
|
||||
|
||||
// Return a new scheme handler instance to handle the request.
|
||||
struct _cef_scheme_handler_t* (CEF_CALLBACK *create)(
|
||||
struct _cef_scheme_handler_factory_t* self);
|
||||
struct _cef_scheme_handler_factory_t* self,
|
||||
const cef_string_t* scheme_name, struct _cef_request_t* request);
|
||||
|
||||
} cef_scheme_handler_factory_t;
|
||||
|
||||
|
103
libcef/origin_whitelist_impl.cc
Normal file
103
libcef/origin_whitelist_impl.cc
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2011 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 "include/cef.h"
|
||||
#include "cef_context.h"
|
||||
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
|
||||
|
||||
using WebKit::WebSecurityPolicy;
|
||||
using WebKit::WebString;
|
||||
|
||||
bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin,
|
||||
const CefString& target_protocol,
|
||||
const CefString& target_domain,
|
||||
bool allow_target_subdomains)
|
||||
{
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string source_url = source_origin;
|
||||
GURL gurl = GURL(source_url);
|
||||
if (gurl.is_empty() || !gurl.is_valid()) {
|
||||
NOTREACHED() << "Invalid source_origin URL: " << source_url;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CefThread::CurrentlyOn(CefThread::UI)) {
|
||||
std::string target_protocol_str = target_protocol;
|
||||
std::string target_domain_str = target_domain;
|
||||
WebSecurityPolicy::addOriginAccessWhitelistEntry(
|
||||
gurl,
|
||||
WebString::fromUTF8(target_protocol_str),
|
||||
WebString::fromUTF8(target_domain_str),
|
||||
allow_target_subdomains);
|
||||
} else {
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
NewRunnableFunction(&CefAddCrossOriginWhitelistEntry, source_origin,
|
||||
target_protocol, target_domain,
|
||||
allow_target_subdomains));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin,
|
||||
const CefString& target_protocol,
|
||||
const CefString& target_domain,
|
||||
bool allow_target_subdomains)
|
||||
{
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string source_url = source_origin;
|
||||
GURL gurl = GURL(source_url);
|
||||
if (gurl.is_empty() || !gurl.is_valid()) {
|
||||
NOTREACHED() << "Invalid source_origin URL: " << source_url;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CefThread::CurrentlyOn(CefThread::UI)) {
|
||||
std::string target_protocol_str = target_protocol;
|
||||
std::string target_domain_str = target_domain;
|
||||
WebSecurityPolicy::removeOriginAccessWhitelistEntry(
|
||||
gurl,
|
||||
WebString::fromUTF8(target_protocol_str),
|
||||
WebString::fromUTF8(target_domain_str),
|
||||
allow_target_subdomains);
|
||||
} else {
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
NewRunnableFunction(&CefRemoveCrossOriginWhitelistEntry, source_origin,
|
||||
target_protocol, target_domain,
|
||||
allow_target_subdomains));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CefClearCrossOriginWhitelist()
|
||||
{
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CefThread::CurrentlyOn(CefThread::UI)) {
|
||||
WebSecurityPolicy::resetOriginAccessWhitelists();
|
||||
} else {
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
NewRunnableFunction(&CefClearCrossOriginWhitelist));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -1,11 +1,18 @@
|
||||
// Copyright (c) 2009 The Chromium Embedded Framework Authors.
|
||||
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "cef_context.h"
|
||||
#include "request_impl.h"
|
||||
#include "response_impl.h"
|
||||
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/string_util.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "googleurl/src/url_util.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
@ -13,43 +20,89 @@
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/http/http_util.h"
|
||||
#include "net/url_request/url_request.h"
|
||||
#include "net/url_request/url_request_about_job.h"
|
||||
#include "net/url_request/url_request_data_job.h"
|
||||
#include "net/url_request/url_request_error_job.h"
|
||||
#include "net/url_request/url_request_file_job.h"
|
||||
#include "net/url_request/url_request_filter.h"
|
||||
#include "net/url_request/url_request_ftp_job.h"
|
||||
#include "net/url_request/url_request_http_job.h"
|
||||
#include "net/url_request/url_request_job.h"
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "tracker.h"
|
||||
#include "cef_context.h"
|
||||
#include "request_impl.h"
|
||||
#include "response_impl.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
using WebKit::WebSecurityPolicy;
|
||||
using WebKit::WebString;
|
||||
|
||||
// Memory manager.
|
||||
namespace {
|
||||
|
||||
base::LazyInstance<CefTrackManager> g_scheme_tracker(base::LINKER_INITIALIZED);
|
||||
|
||||
class TrackBase : public CefTrackObject
|
||||
bool IsStandardScheme(const std::string& scheme)
|
||||
{
|
||||
public:
|
||||
TrackBase(CefBase* base) { base_ = base; }
|
||||
url_parse::Component scheme_comp(0, scheme.length());
|
||||
return url_util::IsStandard(scheme.c_str(), scheme_comp);
|
||||
}
|
||||
|
||||
protected:
|
||||
CefRefPtr<CefBase> base_;
|
||||
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;
|
||||
net::URLRequest::ProtocolFactory* factory;
|
||||
};
|
||||
static const SchemeToFactory kBuiltinFactories[] = {
|
||||
{ "http", net::URLRequestHttpJob::Factory },
|
||||
{ "https", net::URLRequestHttpJob::Factory },
|
||||
{ "file", net::URLRequestFileJob::Factory },
|
||||
{ "ftp", net::URLRequestFtpJob::Factory },
|
||||
{ "about", net::URLRequestAboutJob::Factory },
|
||||
{ "data", net::URLRequestDataJob::Factory },
|
||||
};
|
||||
|
||||
static void TrackAdd(CefTrackObject* object)
|
||||
bool IsBuiltinScheme(const std::string& scheme)
|
||||
{
|
||||
g_scheme_tracker.Pointer()->Add(object);
|
||||
for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i)
|
||||
if (LowerCaseEqualsASCII(scheme, kBuiltinFactories[i].scheme))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
net::URLRequestJob* GetBuiltinSchemeRequestJob(net::URLRequest* request,
|
||||
const std::string& scheme)
|
||||
{
|
||||
// See if the request should be handled by a built-in protocol factory.
|
||||
for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) {
|
||||
if (scheme == kBuiltinFactories[i].scheme) {
|
||||
net::URLRequestJob* job = (kBuiltinFactories[i].factory)(request, scheme);
|
||||
DCHECK(job); // The built-in factories are not expected to fail!
|
||||
return job;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// net::URLRequestJob implementation.
|
||||
|
||||
class CefUrlRequestJob : public net::URLRequestJob {
|
||||
public:
|
||||
CefUrlRequestJob(net::URLRequest* request, CefRefPtr<CefSchemeHandler> handler)
|
||||
CefUrlRequestJob(net::URLRequest* request,
|
||||
CefRefPtr<CefSchemeHandler> handler)
|
||||
: net::URLRequestJob(request),
|
||||
handler_(handler),
|
||||
response_length_(0),
|
||||
@ -244,54 +297,64 @@ private:
|
||||
};
|
||||
|
||||
|
||||
// net::URLRequestFilter clone that manages the CefSchemeHandlerFactory pointers.
|
||||
|
||||
class CefUrlRequestFilter {
|
||||
// Class that manages the CefSchemeHandlerFactory instances.
|
||||
class CefUrlRequestManager {
|
||||
public:
|
||||
// scheme,hostname -> ProtocolFactory
|
||||
typedef std::map<std::pair<std::string, std::string>,
|
||||
CefSchemeHandlerFactory*> HandlerMap;
|
||||
CefUrlRequestManager() {}
|
||||
|
||||
// Singleton instance for use.
|
||||
static CefUrlRequestFilter* GetInstance()
|
||||
{
|
||||
if (!shared_instance_)
|
||||
shared_instance_ = new CefUrlRequestFilter;
|
||||
return shared_instance_;
|
||||
}
|
||||
// Retrieve the singleton instance.
|
||||
static CefUrlRequestManager* GetInstance();
|
||||
|
||||
static net::URLRequestJob* Factory(net::URLRequest* request,
|
||||
const std::string& scheme)
|
||||
bool AddFactory(const std::string& scheme,
|
||||
const std::string& domain,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory)
|
||||
{
|
||||
// Returning null here just means that the built-in handler will be used.
|
||||
return GetInstance()->FindRequestHandler(request, scheme);
|
||||
}
|
||||
if (!factory.get()) {
|
||||
RemoveFactory(scheme, domain);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddHostnameHandler(const std::string& scheme,
|
||||
const std::string& hostname,
|
||||
CefSchemeHandlerFactory* factory)
|
||||
{
|
||||
handler_map_[make_pair(scheme, hostname)] = factory;
|
||||
REQUIRE_IOT();
|
||||
|
||||
std::string scheme_lower = ToLower(scheme);
|
||||
std::string domain_lower = ToLower(domain);
|
||||
|
||||
// Hostname is only supported for standard schemes.
|
||||
if (!IsStandardScheme(scheme_lower))
|
||||
domain_lower.clear();
|
||||
|
||||
handler_map_[make_pair(scheme_lower, domain_lower)] = factory;
|
||||
|
||||
// Register with the ProtocolFactory.
|
||||
net::URLRequest::RegisterProtocolFactory(scheme,
|
||||
&CefUrlRequestFilter::Factory);
|
||||
net::URLRequest::RegisterProtocolFactory(scheme_lower,
|
||||
&CefUrlRequestManager::Factory);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveHostnameHandler(const std::string& scheme,
|
||||
const std::string& hostname)
|
||||
void RemoveFactory(const std::string& scheme,
|
||||
const std::string& domain)
|
||||
{
|
||||
REQUIRE_IOT();
|
||||
|
||||
std::string scheme_lower = ToLower(scheme);
|
||||
std::string domain_lower = ToLower(domain);
|
||||
|
||||
// Hostname is only supported for standard schemes.
|
||||
if (!IsStandardScheme(scheme_lower))
|
||||
domain_lower.clear();
|
||||
|
||||
HandlerMap::iterator iter =
|
||||
handler_map_.find(make_pair(scheme, hostname));
|
||||
DCHECK(iter != handler_map_.end());
|
||||
|
||||
handler_map_.erase(iter);
|
||||
handler_map_.find(make_pair(scheme_lower, domain_lower));
|
||||
if (iter != handler_map_.end())
|
||||
handler_map_.erase(iter);
|
||||
}
|
||||
|
||||
// Clear all the existing URL handlers and unregister with the
|
||||
// ProtocolFactory. Resets the hit count.
|
||||
void ClearHandlers()
|
||||
// Clear all the existing URL handlers and unregister the ProtocolFactory.
|
||||
void ClearFactories()
|
||||
{
|
||||
REQUIRE_IOT();
|
||||
|
||||
// Unregister with the ProtocolFactory.
|
||||
std::set<std::string> schemes;
|
||||
for (HandlerMap::const_iterator i = handler_map_.begin();
|
||||
@ -304,24 +367,73 @@ public:
|
||||
}
|
||||
|
||||
handler_map_.clear();
|
||||
hit_count_ = 0;
|
||||
}
|
||||
|
||||
CefSchemeHandlerFactory* FindRequestHandlerFactory(net::URLRequest* request,
|
||||
const std::string& scheme)
|
||||
// Check if a scheme has already been registered.
|
||||
bool HasRegisteredScheme(const std::string& scheme)
|
||||
{
|
||||
CefSchemeHandlerFactory* factory = NULL;
|
||||
if (request->url().is_valid()) {
|
||||
// Check for a map with a hostname first.
|
||||
const std::string& hostname = request->url().host();
|
||||
std::string scheme_lower = ToLower(scheme);
|
||||
|
||||
HandlerMap::iterator i = handler_map_.find(make_pair(scheme, hostname));
|
||||
// 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.
|
||||
CefRefPtr<CefSchemeHandlerFactory> GetHandlerFactory(
|
||||
net::URLRequest* request, const std::string& scheme)
|
||||
{
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory;
|
||||
|
||||
if (request->url().is_valid() && IsStandardScheme(scheme)) {
|
||||
// Check for a match with a domain first.
|
||||
const std::string& domain = request->url().host();
|
||||
|
||||
HandlerMap::iterator i = handler_map_.find(make_pair(scheme, domain));
|
||||
if (i != handler_map_.end())
|
||||
factory = i->second;
|
||||
}
|
||||
|
||||
if (!factory) {
|
||||
// Check for a map with no specified hostname.
|
||||
if (!factory.get()) {
|
||||
// Check for a match with no specified domain.
|
||||
HandlerMap::iterator i =
|
||||
handler_map_.find(make_pair(scheme, std::string()));
|
||||
if (i != handler_map_.end())
|
||||
@ -331,90 +443,71 @@ public:
|
||||
return factory;
|
||||
}
|
||||
|
||||
// Returns the number of times a handler was used to service a request.
|
||||
int hit_count() const { return hit_count_; }
|
||||
|
||||
protected:
|
||||
CefUrlRequestFilter() : hit_count_(0) { }
|
||||
|
||||
// Helper method that looks up the request in the handler_map_.
|
||||
net::URLRequestJob* FindRequestHandler(net::URLRequest* request,
|
||||
const std::string& scheme)
|
||||
// Create the job that will handle the request. |scheme| will already be in
|
||||
// lower case.
|
||||
net::URLRequestJob* GetRequestJob(net::URLRequest* request,
|
||||
const std::string& scheme)
|
||||
{
|
||||
net::URLRequestJob* job = NULL;
|
||||
CefSchemeHandlerFactory* factory =
|
||||
FindRequestHandlerFactory(request, scheme);
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory =
|
||||
GetHandlerFactory(request, scheme);
|
||||
if (factory) {
|
||||
CefRefPtr<CefSchemeHandler> handler = factory->Create();
|
||||
// Call the handler factory to create the handler for the request.
|
||||
CefRefPtr<CefRequest> requestPtr(new CefRequestImpl());
|
||||
static_cast<CefRequestImpl*>(requestPtr.get())->Set(request);
|
||||
CefRefPtr<CefSchemeHandler> handler = factory->Create(scheme, requestPtr);
|
||||
if (handler.get())
|
||||
job = new CefUrlRequestJob(request, handler);
|
||||
}
|
||||
|
||||
if (job) {
|
||||
DLOG(INFO) << "net::URLRequestFilter hit for " << request->url().spec();
|
||||
hit_count_++;
|
||||
if (!job && IsBuiltinScheme(scheme)) {
|
||||
// Give the built-in scheme handler a chance to handle the request.
|
||||
job = GetBuiltinSchemeRequestJob(request, scheme);
|
||||
}
|
||||
|
||||
if (job)
|
||||
DLOG(INFO) << "CefUrlRequestManager hit for " << request->url().spec();
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
// Maps hostnames to factories. Hostnames take priority over URLs.
|
||||
// Factory method called by the ProtocolFactory. |scheme| will already be in
|
||||
// lower case.
|
||||
static net::URLRequestJob* Factory(net::URLRequest* request,
|
||||
const std::string& scheme)
|
||||
{
|
||||
REQUIRE_IOT();
|
||||
return GetInstance()->GetRequestJob(request, scheme);
|
||||
}
|
||||
|
||||
// Map (scheme, domain) to factories. This map will only be accessed on the IO
|
||||
// thread.
|
||||
typedef std::map<std::pair<std::string, std::string>,
|
||||
CefRefPtr<CefSchemeHandlerFactory> > HandlerMap;
|
||||
HandlerMap handler_map_;
|
||||
|
||||
int hit_count_;
|
||||
// Set of registered schemes. This set may be accessed from multiple threads.
|
||||
typedef std::set<std::string> SchemeSet;
|
||||
SchemeSet scheme_set_;
|
||||
base::Lock scheme_set_lock_;
|
||||
|
||||
private:
|
||||
// Singleton instance.
|
||||
static CefUrlRequestFilter* shared_instance_;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CefUrlRequestFilter);
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CefUrlRequestManager);
|
||||
};
|
||||
|
||||
CefUrlRequestFilter* CefUrlRequestFilter::shared_instance_ = NULL;
|
||||
base::LazyInstance<CefUrlRequestManager> g_manager(base::LINKER_INITIALIZED);
|
||||
|
||||
CefUrlRequestManager* CefUrlRequestManager::GetInstance()
|
||||
{
|
||||
return g_manager.Pointer();
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
|
||||
class SchemeRequestJobWrapper : public CefBase {
|
||||
public:
|
||||
SchemeRequestJobWrapper(const std::string& scheme_name,
|
||||
const std::string& host_name,
|
||||
bool is_standard,
|
||||
CefSchemeHandlerFactory* factory)
|
||||
: scheme_name_(scheme_name), host_name_(host_name),
|
||||
is_standard_(is_standard), factory_(factory)
|
||||
{
|
||||
// The reference will be released when the application exits.
|
||||
TrackAdd(new TrackBase(factory));
|
||||
}
|
||||
|
||||
void RegisterScheme()
|
||||
{
|
||||
if(is_standard_) {
|
||||
// Register the scheme as a standard scheme if it isn't already.
|
||||
url_parse::Component scheme(0, scheme_name_.length());
|
||||
if (!url_util::IsStandard(scheme_name_.c_str(), scheme))
|
||||
url_util::AddStandardScheme(scheme_name_.c_str());
|
||||
}
|
||||
|
||||
// we need to store the pointer of this handler because
|
||||
// we can't pass it as a parameter to the factory method
|
||||
CefUrlRequestFilter::GetInstance()->AddHostnameHandler(
|
||||
scheme_name_, host_name_, factory_);
|
||||
}
|
||||
|
||||
static bool ImplementsThreadSafeReferenceCounting() { return true; }
|
||||
|
||||
private:
|
||||
std::string scheme_name_;
|
||||
std::string host_name_;
|
||||
bool is_standard_;
|
||||
CefSchemeHandlerFactory* factory_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(SchemeRequestJobWrapper);
|
||||
};
|
||||
|
||||
bool CefRegisterScheme(const CefString& scheme_name,
|
||||
const CefString& host_name,
|
||||
bool is_standard,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory)
|
||||
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()) {
|
||||
@ -422,19 +515,60 @@ bool CefRegisterScheme(const CefString& scheme_name,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use a smart pointer for the wrapper object because
|
||||
// RunnableMethodTraits::RetainCallee() (originating from NewRunnableMethod)
|
||||
// will call AddRef() and Release() on the object in debug mode, resulting in
|
||||
// the object being deleted if it doesn't already have a reference.
|
||||
std::string hostNameStr;
|
||||
if (is_standard)
|
||||
hostNameStr = host_name;
|
||||
CefRefPtr<SchemeRequestJobWrapper> wrapper(
|
||||
new SchemeRequestJobWrapper(scheme_name, hostNameStr, is_standard,
|
||||
factory));
|
||||
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,
|
||||
NewRunnableFunction(&CefRegisterCustomScheme, scheme_name, is_standard,
|
||||
is_local, is_display_isolated));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(wrapper.get(),
|
||||
&SchemeRequestJobWrapper::RegisterScheme));
|
||||
bool CefRegisterSchemeHandlerFactory(const CefString& scheme_name,
|
||||
const CefString& domain_name,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory)
|
||||
{
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||
return CefUrlRequestManager::GetInstance()->AddFactory(scheme_name,
|
||||
domain_name,
|
||||
factory);
|
||||
} else {
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE,
|
||||
NewRunnableFunction(&CefRegisterSchemeHandlerFactory, scheme_name,
|
||||
domain_name, factory));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CefClearSchemeHandlerFactories()
|
||||
{
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CefThread::CurrentlyOn(CefThread::IO)) {
|
||||
CefUrlRequestManager::GetInstance()->ClearFactories();
|
||||
} else {
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE,
|
||||
NewRunnableFunction(&CefClearSchemeHandlerFactories));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -12,17 +12,22 @@
|
||||
|
||||
#include "libcef_dll/cpptoc/scheme_handler_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h"
|
||||
#include "libcef_dll/ctocpp/request_ctocpp.h"
|
||||
|
||||
|
||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||
|
||||
struct _cef_scheme_handler_t* CEF_CALLBACK scheme_handler_factory_create(
|
||||
struct _cef_scheme_handler_factory_t* self)
|
||||
struct _cef_scheme_handler_factory_t* self, const cef_string_t* scheme_name,
|
||||
cef_request_t* request)
|
||||
{
|
||||
CefRefPtr<CefSchemeHandler> rv =
|
||||
CefSchemeHandlerFactoryCppToC::Get(self)->Create();
|
||||
CefSchemeHandlerFactoryCppToC::Get(self)->Create(CefString(scheme_name),
|
||||
CefRequestCToCpp::Wrap(request));
|
||||
if (rv.get())
|
||||
return CefSchemeHandlerCppToC::Wrap(rv);
|
||||
|
||||
return CefSchemeHandlerCppToC::Wrap(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,20 +10,25 @@
|
||||
// tools directory for more information.
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/request_cpptoc.h"
|
||||
#include "libcef_dll/ctocpp/scheme_handler_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h"
|
||||
|
||||
|
||||
// VIRTUAL METHODS - Body may be edited by hand.
|
||||
|
||||
CefRefPtr<CefSchemeHandler> CefSchemeHandlerFactoryCToCpp::Create()
|
||||
CefRefPtr<CefSchemeHandler> CefSchemeHandlerFactoryCToCpp::Create(
|
||||
const CefString& scheme_name, CefRefPtr<CefRequest> request)
|
||||
{
|
||||
if(CEF_MEMBER_MISSING(struct_, create))
|
||||
return NULL;
|
||||
|
||||
_cef_scheme_handler_t* rv = struct_->create(struct_);
|
||||
cef_scheme_handler_t* rv = struct_->create(struct_, scheme_name.GetStruct(),
|
||||
CefRequestCppToC::Wrap(request));
|
||||
if (rv)
|
||||
return CefSchemeHandlerCToCpp::Wrap(rv);
|
||||
|
||||
return CefSchemeHandlerCToCpp::Wrap(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,7 +33,8 @@ public:
|
||||
virtual ~CefSchemeHandlerFactoryCToCpp() {}
|
||||
|
||||
// CefSchemeHandlerFactory methods
|
||||
virtual CefRefPtr<CefSchemeHandler> Create() OVERRIDE;
|
||||
virtual CefRefPtr<CefSchemeHandler> Create(const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request) OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // BUILDING_CEF_SHARED
|
||||
|
@ -118,17 +118,71 @@ CEF_EXPORT int cef_register_plugin(const cef_plugin_info_t* plugin_info)
|
||||
return CefRegisterPlugin(*plugin_info);
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_register_scheme(const cef_string_t* scheme_name,
|
||||
const cef_string_t* host_name, int is_standard,
|
||||
CEF_EXPORT int cef_register_custom_scheme(const cef_string_t* scheme_name,
|
||||
int is_standard, int is_local, int is_display_isolated)
|
||||
{
|
||||
DCHECK(scheme_name);
|
||||
if (!scheme_name)
|
||||
return 0;
|
||||
|
||||
return CefRegisterCustomScheme(CefString(scheme_name), is_standard?true:false,
|
||||
is_local?true:false, is_display_isolated?true:false);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
DCHECK(scheme_name);
|
||||
DCHECK(factory);
|
||||
if(!scheme_name || !factory)
|
||||
if (!scheme_name)
|
||||
return 0;
|
||||
|
||||
return CefRegisterScheme(CefString(scheme_name), CefString(host_name),
|
||||
(is_standard?true:false), CefSchemeHandlerFactoryCToCpp::Wrap(factory));
|
||||
CefRefPtr<CefSchemeHandlerFactory> factoryPtr;
|
||||
if (factory)
|
||||
factoryPtr = CefSchemeHandlerFactoryCToCpp::Wrap(factory);
|
||||
|
||||
return CefRegisterSchemeHandlerFactory(CefString(scheme_name),
|
||||
CefString(domain_name), factoryPtr);
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_clear_scheme_handler_factories()
|
||||
{
|
||||
return CefClearSchemeHandlerFactories();
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_add_cross_origin_whitelist_entry(
|
||||
const cef_string_t* source_origin, const cef_string_t* target_protocol,
|
||||
const cef_string_t* target_domain, int allow_target_subdomains)
|
||||
{
|
||||
DCHECK(source_origin);
|
||||
DCHECK(target_protocol);
|
||||
DCHECK(target_domain);
|
||||
if (!source_origin || !target_protocol || !target_domain)
|
||||
return 0;
|
||||
|
||||
return CefAddCrossOriginWhitelistEntry(CefString(source_origin),
|
||||
CefString(target_protocol), CefString(target_domain),
|
||||
allow_target_subdomains?true:false);
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_remove_cross_origin_whitelist_entry(
|
||||
const cef_string_t* source_origin, const cef_string_t* target_protocol,
|
||||
const cef_string_t* target_domain, int allow_target_subdomains)
|
||||
{
|
||||
DCHECK(source_origin);
|
||||
DCHECK(target_protocol);
|
||||
DCHECK(target_domain);
|
||||
if (!source_origin || !target_protocol || !target_domain)
|
||||
return 0;
|
||||
|
||||
return CefRemoveCrossOriginWhitelistEntry(CefString(source_origin),
|
||||
CefString(target_protocol), CefString(target_domain),
|
||||
allow_target_subdomains?true:false);
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_clear_cross_origin_whitelist()
|
||||
{
|
||||
return CefClearCrossOriginWhitelist();
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId)
|
||||
|
@ -99,13 +99,55 @@ bool CefRegisterPlugin(const CefPluginInfo& plugin_info)
|
||||
return cef_register_plugin(&plugin_info)?true:false;
|
||||
}
|
||||
|
||||
bool CefRegisterScheme(const CefString& scheme_name,
|
||||
const CefString& host_name,
|
||||
bool is_standard,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory)
|
||||
bool CefRegisterCustomScheme(const CefString& scheme_name,
|
||||
bool is_standard,
|
||||
bool is_local,
|
||||
bool is_display_isolated)
|
||||
{
|
||||
return cef_register_scheme(scheme_name.GetStruct(), host_name.GetStruct(),
|
||||
is_standard, CefSchemeHandlerFactoryCppToC::Wrap(factory))?true:false;
|
||||
return cef_register_custom_scheme(scheme_name.GetStruct(), is_standard,
|
||||
is_local, is_display_isolated)?true:false;
|
||||
}
|
||||
|
||||
bool CefRegisterSchemeHandlerFactory(const CefString& scheme_name,
|
||||
const CefString& domain_name,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory)
|
||||
{
|
||||
cef_scheme_handler_factory_t* factory_struct = NULL;
|
||||
if (factory.get())
|
||||
factory_struct = CefSchemeHandlerFactoryCppToC::Wrap(factory);
|
||||
|
||||
return cef_register_scheme_handler_factory(scheme_name.GetStruct(),
|
||||
domain_name.GetStruct(), factory_struct)?true:false;
|
||||
}
|
||||
|
||||
bool CefClearSchemeHandlerFactories()
|
||||
{
|
||||
return cef_clear_scheme_handler_factories()?true:false;
|
||||
}
|
||||
|
||||
bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin,
|
||||
const CefString& target_protocol,
|
||||
const CefString& target_domain,
|
||||
bool allow_target_subdomains)
|
||||
{
|
||||
return cef_add_cross_origin_whitelist_entry(source_origin.GetStruct(),
|
||||
target_protocol.GetStruct(), target_domain.GetStruct(),
|
||||
allow_target_subdomains)?true:false;
|
||||
}
|
||||
|
||||
bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin,
|
||||
const CefString& target_protocol,
|
||||
const CefString& target_domain,
|
||||
bool allow_target_subdomains)
|
||||
{
|
||||
return cef_remove_cross_origin_whitelist_entry(source_origin.GetStruct(),
|
||||
target_protocol.GetStruct(), target_domain.GetStruct(),
|
||||
allow_target_subdomains)?true:false;
|
||||
}
|
||||
|
||||
bool CefClearCrossOriginWhitelist()
|
||||
{
|
||||
return cef_clear_cross_origin_whitelist()?true:false;
|
||||
}
|
||||
|
||||
bool CefCurrentlyOn(CefThreadId threadId)
|
||||
|
@ -141,7 +141,8 @@ class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory
|
||||
{
|
||||
public:
|
||||
// Return a new scheme handler instance to handle the request.
|
||||
virtual CefRefPtr<CefSchemeHandler> Create()
|
||||
virtual CefRefPtr<CefSchemeHandler> Create(const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request)
|
||||
{
|
||||
REQUIRE_IO_THREAD();
|
||||
return new ClientSchemeHandler();
|
||||
@ -152,7 +153,9 @@ public:
|
||||
|
||||
void InitSchemeTest()
|
||||
{
|
||||
CefRegisterScheme("client", "tests", true, new ClientSchemeHandlerFactory());
|
||||
CefRegisterCustomScheme("client", true, false, false);
|
||||
CefRegisterSchemeHandlerFactory("client", "tests",
|
||||
new ClientSchemeHandlerFactory());
|
||||
}
|
||||
|
||||
void RunSchemeTest(CefRefPtr<CefBrowser> browser)
|
||||
|
@ -2,6 +2,7 @@
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "include/cef_runnable.h"
|
||||
#include "test_handler.h"
|
||||
|
||||
namespace {
|
||||
@ -10,6 +11,8 @@ class TestResults
|
||||
{
|
||||
public:
|
||||
TestResults()
|
||||
: status_code(0),
|
||||
sub_status_code(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -18,22 +21,45 @@ public:
|
||||
url.clear();
|
||||
html.clear();
|
||||
status_code = 0;
|
||||
redirect_url.clear();
|
||||
sub_url.clear();
|
||||
sub_html.clear();
|
||||
sub_status_code = 0;
|
||||
sub_allow_origin.clear();
|
||||
exit_url.clear();
|
||||
got_request.reset();
|
||||
got_read.reset();
|
||||
got_output.reset();
|
||||
got_redirect.reset();
|
||||
got_error.reset();
|
||||
got_sub_request.reset();
|
||||
got_sub_read.reset();
|
||||
got_sub_success.reset();
|
||||
}
|
||||
|
||||
std::string url;
|
||||
std::string html;
|
||||
int status_code;
|
||||
|
||||
// Used for testing redirects
|
||||
std::string redirect_url;
|
||||
|
||||
// Used for testing XHR requests
|
||||
std::string sub_url;
|
||||
std::string sub_html;
|
||||
int sub_status_code;
|
||||
std::string sub_allow_origin;
|
||||
std::string exit_url;
|
||||
|
||||
TrackCallback
|
||||
got_request,
|
||||
got_read,
|
||||
got_output,
|
||||
got_redirect;
|
||||
got_redirect,
|
||||
got_error,
|
||||
got_sub_request,
|
||||
got_sub_read,
|
||||
got_sub_success;
|
||||
};
|
||||
|
||||
class TestSchemeHandler : public TestHandler
|
||||
@ -55,9 +81,18 @@ public:
|
||||
NavType navType,
|
||||
bool isRedirect) OVERRIDE
|
||||
{
|
||||
std::string newUrl = request->GetURL();
|
||||
if (!test_results_->exit_url.empty() &&
|
||||
newUrl.find(test_results_->exit_url) != std::string::npos) {
|
||||
// XHR tests use an exit URL to destroy the test.
|
||||
if (newUrl.find("SUCCESS") != std::string::npos)
|
||||
test_results_->got_sub_success.yes();
|
||||
DestroyTest();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isRedirect) {
|
||||
test_results_->got_redirect.yes();
|
||||
std::string newUrl = request->GetURL();
|
||||
EXPECT_EQ(newUrl, test_results_->redirect_url);
|
||||
|
||||
// No read should have occurred for the redirect.
|
||||
@ -76,15 +111,34 @@ public:
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) OVERRIDE
|
||||
{
|
||||
// Test that the output is correct.
|
||||
std::string output = frame->GetSource();
|
||||
if (output == test_results_->html)
|
||||
test_results_->got_output.yes();
|
||||
std::string url = frame->GetURL();
|
||||
if (url == test_results_->url || test_results_->status_code != 200) {
|
||||
if (test_results_->sub_url.empty()) {
|
||||
// Test that the output is correct.
|
||||
std::string output = frame->GetSource();
|
||||
if (output == test_results_->html)
|
||||
test_results_->got_output.yes();
|
||||
} else {
|
||||
test_results_->got_output.yes();
|
||||
}
|
||||
|
||||
// Test that the status code is correct.
|
||||
EXPECT_EQ(httpStatusCode, test_results_->status_code);
|
||||
// Test that the status code is correct.
|
||||
EXPECT_EQ(httpStatusCode, test_results_->status_code);
|
||||
|
||||
if (test_results_->sub_url.empty())
|
||||
DestroyTest();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool OnLoadError(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
ErrorCode errorCode,
|
||||
const CefString& failedUrl,
|
||||
CefString& errorText) OVERRIDE
|
||||
{
|
||||
test_results_->got_error.yes();
|
||||
DestroyTest();
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -95,7 +149,7 @@ class ClientSchemeHandler : public CefSchemeHandler
|
||||
{
|
||||
public:
|
||||
ClientSchemeHandler(TestResults* tr)
|
||||
: test_results_(tr), offset_(0) {}
|
||||
: test_results_(tr), offset_(0), is_sub_(false) {}
|
||||
|
||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefString& redirectUrl,
|
||||
@ -104,20 +158,43 @@ public:
|
||||
{
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
test_results_->got_request.yes();
|
||||
|
||||
std::string url = request->GetURL();
|
||||
EXPECT_EQ(url, test_results_->url);
|
||||
is_sub_ = (!test_results_->sub_url.empty() &&
|
||||
test_results_->sub_url == url);
|
||||
|
||||
response->SetStatus(test_results_->status_code);
|
||||
if (is_sub_) {
|
||||
test_results_->got_sub_request.yes();
|
||||
response->SetStatus(test_results_->sub_status_code);
|
||||
|
||||
if (!test_results_->redirect_url.empty()) {
|
||||
redirectUrl = test_results_->redirect_url;
|
||||
return true;
|
||||
} else if (!test_results_->html.empty()) {
|
||||
response->SetMimeType("text/html");
|
||||
*response_length = test_results_->html.size();
|
||||
return true;
|
||||
if (!test_results_->sub_allow_origin.empty()) {
|
||||
// Set the Access-Control-Allow-Origin header to allow cross-domain
|
||||
// scripting.
|
||||
CefResponse::HeaderMap headers;
|
||||
headers.insert(std::make_pair("Access-Control-Allow-Origin",
|
||||
test_results_->sub_allow_origin));
|
||||
response->SetHeaderMap(headers);
|
||||
}
|
||||
|
||||
if (!test_results_->sub_html.empty()) {
|
||||
response->SetMimeType("text/html");
|
||||
*response_length = test_results_->sub_html.size();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
EXPECT_EQ(url, test_results_->url);
|
||||
|
||||
test_results_->got_request.yes();
|
||||
|
||||
response->SetStatus(test_results_->status_code);
|
||||
|
||||
if (!test_results_->redirect_url.empty()) {
|
||||
redirectUrl = test_results_->redirect_url;
|
||||
return true;
|
||||
} else if (!test_results_->html.empty()) {
|
||||
response->SetMimeType("text/html");
|
||||
*response_length = test_results_->html.size();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -132,18 +209,26 @@ public:
|
||||
{
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
test_results_->got_read.yes();
|
||||
std::string* data;
|
||||
|
||||
if (is_sub_) {
|
||||
test_results_->got_sub_read.yes();
|
||||
data = &test_results_->sub_html;
|
||||
} else {
|
||||
test_results_->got_read.yes();
|
||||
data = &test_results_->html;
|
||||
}
|
||||
|
||||
bool has_data = false;
|
||||
*bytes_read = 0;
|
||||
|
||||
AutoLock lock_scope(this);
|
||||
|
||||
size_t size = test_results_->html.size();
|
||||
size_t size = data->size();
|
||||
if(offset_ < size) {
|
||||
int transfer_size =
|
||||
std::min(bytes_to_read, static_cast<int>(size - offset_));
|
||||
memcpy(data_out, test_results_->html.c_str() + offset_, transfer_size);
|
||||
memcpy(data_out, data->c_str() + offset_, transfer_size);
|
||||
offset_ += transfer_size;
|
||||
|
||||
*bytes_read = transfer_size;
|
||||
@ -156,6 +241,7 @@ public:
|
||||
private:
|
||||
TestResults* test_results_;
|
||||
size_t offset_;
|
||||
bool is_sub_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
||||
IMPLEMENT_LOCKING(ClientSchemeHandler);
|
||||
@ -167,7 +253,8 @@ public:
|
||||
ClientSchemeHandlerFactory(TestResults* tr)
|
||||
: test_results_(tr){}
|
||||
|
||||
virtual CefRefPtr<CefSchemeHandler> Create()
|
||||
virtual CefRefPtr<CefSchemeHandler> Create(const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request)
|
||||
{
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
return new ClientSchemeHandler(test_results_);
|
||||
@ -181,35 +268,145 @@ public:
|
||||
// Global test results object.
|
||||
TestResults g_TestResults;
|
||||
|
||||
void CreateStandardTestScheme()
|
||||
void NotifyEvent(base::WaitableEvent* event)
|
||||
{
|
||||
g_TestResults.reset();
|
||||
static bool registered = false;
|
||||
if (!registered) {
|
||||
CefRegisterScheme("stdscheme", "tests", true,
|
||||
new ClientSchemeHandlerFactory(&g_TestResults));
|
||||
registered = true;
|
||||
}
|
||||
event->Signal();
|
||||
}
|
||||
|
||||
void CreateNonStandardTestScheme()
|
||||
// Post a task to the specified thread and wait for the task to execute as
|
||||
// indication that all previously pending tasks on that thread have completed.
|
||||
void WaitForThread(CefThreadId thread_id)
|
||||
{
|
||||
base::WaitableEvent event(true, false);
|
||||
CefPostTask(thread_id, NewCefRunnableFunction(&NotifyEvent, &event));
|
||||
event.Wait();
|
||||
}
|
||||
|
||||
#define WaitForIOThread() WaitForThread(TID_IO)
|
||||
#define WaitForUIThread() WaitForThread(TID_UI)
|
||||
|
||||
// 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 bool registered = false;
|
||||
if (!registered) {
|
||||
CefRegisterScheme("nonstdscheme", CefString(), false,
|
||||
new ClientSchemeHandlerFactory(&g_TestResults));
|
||||
registered = true;
|
||||
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)));
|
||||
WaitForIOThread();
|
||||
}
|
||||
|
||||
void ClearTestSchemes()
|
||||
{
|
||||
EXPECT_TRUE(CefClearSchemeHandlerFactories());
|
||||
WaitForIOThread();
|
||||
}
|
||||
|
||||
void SetUpXHR(const std::string& url, const std::string& sub_url,
|
||||
const std::string& sub_allow_origin = std::string())
|
||||
{
|
||||
g_TestResults.sub_url = sub_url;
|
||||
g_TestResults.sub_html = "SUCCESS";
|
||||
g_TestResults.sub_status_code = 200;
|
||||
g_TestResults.sub_allow_origin = sub_allow_origin;
|
||||
|
||||
g_TestResults.url = url;
|
||||
std::stringstream ss;
|
||||
ss << "<html><head>\
|
||||
<script language=\"JavaScript\">\
|
||||
function execXMLHttpRequest() {\
|
||||
var result = 'FAILURE';\
|
||||
try {\
|
||||
xhr = new XMLHttpRequest();\
|
||||
xhr.open(\"GET\", \"" << sub_url.c_str() << "\", false);\
|
||||
xhr.send();\
|
||||
result = xhr.responseText;\
|
||||
} catch(e) {}\
|
||||
document.location = \"http://tests/exit?result=\"+result;\
|
||||
}\
|
||||
</script>\
|
||||
</head><body onload=\"execXMLHttpRequest();\">\
|
||||
Running execXMLHttpRequest...\
|
||||
</body></html>";
|
||||
g_TestResults.html = ss.str();
|
||||
g_TestResults.status_code = 200;
|
||||
|
||||
g_TestResults.exit_url = "http://tests/exit";
|
||||
}
|
||||
|
||||
void SetUpXSS(const std::string& url, const std::string& sub_url,
|
||||
const std::string& domain = std::string())
|
||||
{
|
||||
// 1. Load |url| which contains an iframe.
|
||||
// 2. The iframe loads |xss_url|.
|
||||
// 3. |xss_url| tries to call a JS function in |url|.
|
||||
// 4. |url| tries to call a JS function in |xss_url|.
|
||||
|
||||
std::stringstream ss;
|
||||
std::string domain_line;
|
||||
if (!domain.empty())
|
||||
domain_line = "document.domain = '" + domain + "';";
|
||||
|
||||
g_TestResults.sub_url = sub_url;
|
||||
ss << "<html><head>\
|
||||
<script language=\"JavaScript\">" << domain_line << "\
|
||||
function getResult() {\
|
||||
return 'SUCCESS';\
|
||||
}\
|
||||
function execXSSRequest() {\
|
||||
var result = 'FAILURE';\
|
||||
try {\
|
||||
result = parent.getResult();\
|
||||
} catch(e) {}\
|
||||
document.location = \"http://tests/exit?result=\"+result;\
|
||||
}\
|
||||
</script>\
|
||||
</head><body onload=\"execXSSRequest();\">\
|
||||
Running execXSSRequest...\
|
||||
</body></html>";
|
||||
g_TestResults.sub_html = ss.str();
|
||||
g_TestResults.sub_status_code = 200;
|
||||
|
||||
g_TestResults.url = url;
|
||||
ss.str("");
|
||||
ss << "<html><head>\
|
||||
<script language=\"JavaScript\">" << domain_line << "\
|
||||
function getResult() {\
|
||||
try {\
|
||||
return document.getElementById('s').contentWindow.getResult();\
|
||||
} catch(e) {}\
|
||||
return 'FAILURE';\
|
||||
}\
|
||||
</script>\
|
||||
</head><body>\
|
||||
<iframe src=\"" << sub_url.c_str() << "\" id=\"s\">\
|
||||
</body></html>";
|
||||
g_TestResults.html = ss.str();
|
||||
g_TestResults.status_code = 200;
|
||||
|
||||
g_TestResults.exit_url = "http://tests/exit";
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
// Test that a standard scheme can return normal results.
|
||||
TEST(SchemeHandlerTest, StandardSchemeNormalResponse)
|
||||
// Test that scheme registration/unregistration works as expected.
|
||||
TEST(SchemeHandlerTest, Registration)
|
||||
{
|
||||
CreateStandardTestScheme();
|
||||
g_TestResults.url = "stdscheme://tests/run.html";
|
||||
RegisterTestScheme("customstd", "test");
|
||||
g_TestResults.url = "customstd://test/run.html";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>Success!</h1></body></html>";
|
||||
g_TestResults.status_code = 200;
|
||||
@ -220,90 +417,41 @@ TEST(SchemeHandlerTest, StandardSchemeNormalResponse)
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
}
|
||||
|
||||
// Test that a standard scheme can return an error code.
|
||||
TEST(SchemeHandlerTest, StandardSchemeErrorResponse)
|
||||
{
|
||||
CreateStandardTestScheme();
|
||||
g_TestResults.url = "stdscheme://tests/run.html";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>404</h1></body></html>";
|
||||
g_TestResults.status_code = 404;
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
// Unregister the handler.
|
||||
EXPECT_TRUE(CefRegisterSchemeHandlerFactory("customstd", "test", NULL));
|
||||
WaitForIOThread();
|
||||
|
||||
g_TestResults.got_request.reset();
|
||||
g_TestResults.got_read.reset();
|
||||
g_TestResults.got_output.reset();
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_error);
|
||||
EXPECT_FALSE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
|
||||
// Re-register the handler.
|
||||
EXPECT_TRUE(CefRegisterSchemeHandlerFactory("customstd", "test",
|
||||
new ClientSchemeHandlerFactory(&g_TestResults)));
|
||||
WaitForIOThread();
|
||||
|
||||
g_TestResults.got_error.reset();
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that standard scheme handling fails when the scheme name is incorrect.
|
||||
TEST(SchemeHandlerTest, StandardSchemeNameNotHandled)
|
||||
// Test that a custom standard scheme can return normal results.
|
||||
TEST(SchemeHandlerTest, CustomStandardNormalResponse)
|
||||
{
|
||||
CreateStandardTestScheme();
|
||||
g_TestResults.url = "stdscheme2://tests/run.html";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_FALSE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
}
|
||||
|
||||
// Test that standard scheme handling fails when the domain name is incorrect.
|
||||
TEST(SchemeHandlerTest, StandardSchemeDomainNotHandled)
|
||||
{
|
||||
CreateStandardTestScheme();
|
||||
g_TestResults.url = "stdscheme://tests2/run.html";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_FALSE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
}
|
||||
|
||||
// Test that a standard scheme can return no response.
|
||||
TEST(SchemeHandlerTest, StandardSchemeNoResponse)
|
||||
{
|
||||
CreateStandardTestScheme();
|
||||
g_TestResults.url = "stdscheme://tests/run.html";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
}
|
||||
|
||||
// Test that a standard scheme can generate redirects.
|
||||
TEST(SchemeHandlerTest, StandardSchemeRedirect)
|
||||
{
|
||||
CreateStandardTestScheme();
|
||||
g_TestResults.url = "stdscheme://tests/run.html";
|
||||
g_TestResults.redirect_url = "stdscheme://tests/redirect.html";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>Redirected</h1></body></html>";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_redirect);
|
||||
}
|
||||
|
||||
// Test that a non-standard scheme can return normal results.
|
||||
TEST(SchemeHandlerTest, NonStandardSchemeNormalResponse)
|
||||
{
|
||||
CreateNonStandardTestScheme();
|
||||
g_TestResults.url = "nonstdscheme:some%20value";
|
||||
RegisterTestScheme("customstd", "test");
|
||||
g_TestResults.url = "customstd://test/run.html";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>Success!</h1></body></html>";
|
||||
g_TestResults.status_code = 200;
|
||||
@ -314,13 +462,34 @@ TEST(SchemeHandlerTest, NonStandardSchemeNormalResponse)
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a non-standard scheme can return an error code.
|
||||
TEST(SchemeHandlerTest, NonStandardSchemeErrorResponse)
|
||||
// Test that a custom nonstandard scheme can return normal results.
|
||||
TEST(SchemeHandlerTest, CustomNonStandardNormalResponse)
|
||||
{
|
||||
CreateNonStandardTestScheme();
|
||||
g_TestResults.url = "nonstdscheme:some%20value";
|
||||
RegisterTestScheme("customnonstd", std::string());
|
||||
g_TestResults.url = "customnonstd:some%20value";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>Success!</h1></body></html>";
|
||||
g_TestResults.status_code = 200;
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme can return an error code.
|
||||
TEST(SchemeHandlerTest, CustomStandardErrorResponse)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test");
|
||||
g_TestResults.url = "customstd://test/run.html";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>404</h1></body></html>";
|
||||
g_TestResults.status_code = 404;
|
||||
@ -331,14 +500,35 @@ TEST(SchemeHandlerTest, NonStandardSchemeErrorResponse)
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that non-standard scheme handling fails when the scheme name is
|
||||
// Test that a custom nonstandard scheme can return an error code.
|
||||
TEST(SchemeHandlerTest, CustomNonStandardErrorResponse)
|
||||
{
|
||||
RegisterTestScheme("customnonstd", std::string());
|
||||
g_TestResults.url = "customnonstd:some%20value";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>404</h1></body></html>";
|
||||
g_TestResults.status_code = 404;
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that custom standard scheme handling fails when the scheme name is
|
||||
// incorrect.
|
||||
TEST(SchemeHandlerTest, NonStandardSchemeNameNotHandled)
|
||||
TEST(SchemeHandlerTest, CustomStandardNameNotHandled)
|
||||
{
|
||||
CreateNonStandardTestScheme();
|
||||
g_TestResults.url = "nonstdscheme2:some%20value";
|
||||
RegisterTestScheme("customstd", "test");
|
||||
g_TestResults.url = "customstd2://test/run.html";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
@ -346,13 +536,49 @@ TEST(SchemeHandlerTest, NonStandardSchemeNameNotHandled)
|
||||
EXPECT_FALSE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a non-standard scheme can return no response.
|
||||
TEST(SchemeHandlerTest, NonStandardSchemeNoResponse)
|
||||
// Test that custom nonstandard scheme handling fails when the scheme name is
|
||||
// incorrect.
|
||||
TEST(SchemeHandlerTest, CustomNonStandardNameNotHandled)
|
||||
{
|
||||
CreateNonStandardTestScheme();
|
||||
g_TestResults.url = "nonstdscheme:some%20value";
|
||||
RegisterTestScheme("customnonstd", std::string());
|
||||
g_TestResults.url = "customnonstd2:some%20value";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_FALSE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that custom standard scheme handling fails when the domain name is
|
||||
// incorrect.
|
||||
TEST(SchemeHandlerTest, CustomStandardDomainNotHandled)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test");
|
||||
g_TestResults.url = "customstd://noexist/run.html";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_FALSE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme can return no response.
|
||||
TEST(SchemeHandlerTest, CustomStandardNoResponse)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test");
|
||||
g_TestResults.url = "customstd://test/run.html";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
@ -360,14 +586,32 @@ TEST(SchemeHandlerTest, NonStandardSchemeNoResponse)
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a non-standard scheme can generate redirects.
|
||||
TEST(SchemeHandlerTest, NonStandardSchemeRedirect)
|
||||
// Test that a custom nonstandard scheme can return no response.
|
||||
TEST(SchemeHandlerTest, CustomNonStandardNoResponse)
|
||||
{
|
||||
CreateNonStandardTestScheme();
|
||||
g_TestResults.url = "nonstdscheme:some%20value";
|
||||
g_TestResults.redirect_url = "nonstdscheme:some%20other%20value";
|
||||
RegisterTestScheme("customnonstd", std::string());
|
||||
g_TestResults.url = "customnonstd:some%20value";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_FALSE(g_TestResults.got_read);
|
||||
EXPECT_FALSE(g_TestResults.got_output);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme can generate redirects.
|
||||
TEST(SchemeHandlerTest, CustomStandardRedirect)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test");
|
||||
g_TestResults.url = "customstd://test/run.html";
|
||||
g_TestResults.redirect_url = "customstd://test/redirect.html";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>Redirected</h1></body></html>";
|
||||
|
||||
@ -378,4 +622,314 @@ TEST(SchemeHandlerTest, NonStandardSchemeRedirect)
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_redirect);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom nonstandard scheme can generate redirects.
|
||||
TEST(SchemeHandlerTest, CustomNonStandardRedirect)
|
||||
{
|
||||
RegisterTestScheme("customnonstd", std::string());
|
||||
g_TestResults.url = "customnonstd:some%20value";
|
||||
g_TestResults.redirect_url = "customnonstd:some%20other%20value";
|
||||
g_TestResults.html =
|
||||
"<html><head></head><body><h1>Redirected</h1></body></html>";
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_redirect);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme can generate same origin XHR requests.
|
||||
TEST(SchemeHandlerTest, CustomStandardXHRSameOrigin)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test");
|
||||
SetUpXHR("customstd://test/run.html",
|
||||
"customstd://test/xhr.html");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom nonstandard scheme can generate same origin XHR requests.
|
||||
TEST(SchemeHandlerTest, CustomNonStandardXHRSameOrigin)
|
||||
{
|
||||
RegisterTestScheme("customnonstd", std::string());
|
||||
SetUpXHR("customnonstd:some%20value",
|
||||
"customnonstd:xhr%20value");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
// Test that a custom standard scheme can generate same origin XSS requests.
|
||||
TEST(SchemeHandlerTest, CustomStandardXSSSameOrigin)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test");
|
||||
SetUpXSS("customstd://test/run.html",
|
||||
"customstd://test/iframe.html");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom nonstandard scheme can generate same origin XSS requests.
|
||||
TEST(SchemeHandlerTest, CustomNonStandardXSSSameOrigin)
|
||||
{
|
||||
RegisterTestScheme("customnonstd", std::string());
|
||||
SetUpXSS("customnonstd:some%20value",
|
||||
"customnonstd:xhr%20value");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme cannot generate cross-domain XHR requests
|
||||
// by default.
|
||||
TEST(SchemeHandlerTest, CustomStandardXHRDifferentOrigin)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test1");
|
||||
RegisterTestScheme("customstd", "test2");
|
||||
SetUpXHR("customstd://test1/run.html",
|
||||
"customstd://test2/xhr.html");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_request);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_read);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme cannot generate cross-domain XSS requests
|
||||
// by default.
|
||||
TEST(SchemeHandlerTest, CustomStandardXSSDifferentOrigin)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test1");
|
||||
RegisterTestScheme("customstd", "test2");
|
||||
SetUpXSS("customstd://test1/run.html",
|
||||
"customstd://test2/iframe.html");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that an HTTP scheme cannot generate cross-domain XHR requests by
|
||||
// default.
|
||||
TEST(SchemeHandlerTest, HttpXHRDifferentOrigin)
|
||||
{
|
||||
RegisterTestScheme("http", "test1");
|
||||
RegisterTestScheme("http", "test2");
|
||||
SetUpXHR("http://test1/run.html",
|
||||
"http://test2/xhr.html");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that an HTTP scheme cannot generate cross-domain XSS requests by
|
||||
// default.
|
||||
TEST(SchemeHandlerTest, HttpXSSDifferentOrigin)
|
||||
{
|
||||
RegisterTestScheme("http", "test1");
|
||||
RegisterTestScheme("http", "test2");
|
||||
SetUpXHR("http://test1/run.html",
|
||||
"http://test2/xhr.html");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme cannot generate cross-domain XHR requests
|
||||
// even when setting the Access-Control-Allow-Origin header.
|
||||
TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithHeader)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test1");
|
||||
RegisterTestScheme("customstd", "test2");
|
||||
SetUpXHR("customstd://test1/run.html",
|
||||
"customstd://test2/xhr.html",
|
||||
"customstd://test1");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_request);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_read);
|
||||
EXPECT_FALSE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme can generate cross-domain XHR requests
|
||||
// when using the cross-origin whitelist.
|
||||
TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelist)
|
||||
{
|
||||
RegisterTestScheme("customstd", "test1");
|
||||
RegisterTestScheme("customstd", "test2");
|
||||
SetUpXHR("customstd://test1/run.html",
|
||||
"customstd://test2/xhr.html");
|
||||
|
||||
EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
|
||||
"test2", false));
|
||||
WaitForUIThread();
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
EXPECT_TRUE(CefClearCrossOriginWhitelist());
|
||||
WaitForUIThread();
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that an HTTP scheme can generate cross-domain XHR requests when setting
|
||||
// the Access-Control-Allow-Origin header.
|
||||
TEST(SchemeHandlerTest, HttpXHRDifferentOriginWithHeader)
|
||||
{
|
||||
RegisterTestScheme("http", "test1");
|
||||
RegisterTestScheme("http", "test2");
|
||||
SetUpXHR("http://test1/run.html",
|
||||
"http://test2/xhr.html",
|
||||
"http://test1");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that a custom standard scheme can generate cross-domain XSS requests
|
||||
// when using document.domain.
|
||||
TEST(SchemeHandlerTest, CustomStandardXSSDifferentOriginWithDomain)
|
||||
{
|
||||
RegisterTestScheme("customstd", "a.test");
|
||||
RegisterTestScheme("customstd", "b.test");
|
||||
SetUpXSS("customstd://a.test/run.html",
|
||||
"customstd://b.test/iframe.html",
|
||||
"test");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
||||
// Test that an HTTP scheme can generate cross-domain XSS requests when using
|
||||
// document.domain.
|
||||
TEST(SchemeHandlerTest, HttpXSSDifferentOriginWithDomain)
|
||||
{
|
||||
RegisterTestScheme("http", "a.test");
|
||||
RegisterTestScheme("http", "b.test");
|
||||
SetUpXSS("http://a.test/run.html",
|
||||
"http://b.test/iframe.html",
|
||||
"test");
|
||||
|
||||
CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(g_TestResults.got_request);
|
||||
EXPECT_TRUE(g_TestResults.got_read);
|
||||
EXPECT_TRUE(g_TestResults.got_output);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_request);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_read);
|
||||
EXPECT_TRUE(g_TestResults.got_sub_success);
|
||||
|
||||
ClearTestSchemes();
|
||||
}
|
||||
|
@ -123,6 +123,9 @@ public:
|
||||
|
||||
// Wait for the test to complete
|
||||
completion_event_.Wait();
|
||||
|
||||
// Reset the event so the same test can be executed again.
|
||||
completion_event_.Reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
Loading…
x
Reference in New Issue
Block a user