Compare commits

...

31 Commits
3904 ... 3770

Author SHA1 Message Date
Riku Palomäki
16a67c4507 Fix gclient_util after depot_tools changes (fixes issue #2736) 2019-08-05 14:07:23 -04:00
Dmitry Azaraev
0ebdb473b1 Fix missing marshaling for CefSettings::root_cache_path member (fixes issue #2740) 2019-08-05 14:07:16 -04:00
Marshall Greenblatt
c81164e2ce Fix crash on DevTools remote debugging of WebWorkers (fixes issue #2605) 2019-07-26 09:49:58 -04:00
Marshall Greenblatt
e0be1d916d Fix missing cookie after redirect response with filter (fixes issue #2689, see issue #2622) 2019-07-25 17:02:24 -04:00
Marshall Greenblatt
d9915d728f Fix option for persisting session cookies (fixes issue #2720, see issue #2622) 2019-07-25 15:29:24 -04:00
Marshall Greenblatt
5656baa197 Fix C compile error due to unintentional C++ include (fixes issue #2728) 2019-07-25 13:42:31 -04:00
Marshall Greenblatt
fed0e1826a macOS: Fix alert dialog display (fixes issue #2726) 2019-07-25 12:36:50 -04:00
Dmitry Azaraev
a9c022bd11 Fix typo in documentation for CefResourceHandler::Skip 2019-07-25 12:36:42 -04:00
Marshall Greenblatt
84fed5dc0e Fix PDF load in <embed> and <object> tags (fixes issue #2727, see issue #2622) 2019-07-24 20:29:15 -04:00
Marshall Greenblatt
b34af23449 Fix crash on shutdown with PDF viewer and multi-threaded message loop (fixes issue #2709, see issue #2622)
Requests from the PDF viewer are not associated with a CefBrowser. Consequently,
the InterceptedRequestHandler for those requests will register as an observer of
CefContext destruction. When the browser is closed the InterceptedRequestHandler
is destroyed and an async task is posted to remove/delete the observer on the UI
thread. If CefShutdown is then called the task may execute after shutdown has
started, in which case CONTEXT_STATE_VALID() will return false. We still need to
remove the observer in this case to avoid a use-after-free in
FinishShutdownOnUIThread.
2019-07-23 15:29:46 -04:00
Dmitry Azaraev
94d09f80e7 Fix typo in documentation for cef_settings_t::cache_path. 2019-07-23 15:29:40 -04:00
Marshall Greenblatt
1c3d34bc32 Fix crash when extensions are disabled (fixes issue #2708, see issue #2622) 2019-07-23 12:22:46 -04:00
Riku Palomäki
4210896724 Fix dangling pointers in CefAudioMirrorDestination (fixes issue #2713). 2019-07-16 17:45:20 -04:00
Isaac Devine
1931b9c969 Fix race with multi-threaded message loop (fixes issue #2668).
Remove the local thread object in favor of setting the ui_thread_ field
directly. This avoids the race between ui_thread_.swap(thread) and
CefUIThread::InitializeBrowserRunner.
2019-07-16 17:45:10 -04:00
Alexander Guettler
fdd887b677 Fix dangling pointers in CefScopedArgArray (fixes issue #2704). 2019-07-16 17:44:59 -04:00
Masako Toda
849a6e64dc Fix redirect of requests with credentials mode 'include' (fixes issue #2699, see issue #2622).
Modifying the URL in OnBeforeResourceLoad causes an internal redirect response.
In cases where the request is cross-origin and credentials mode is 'include'
the redirect response must include the "Access-Control-Allow-Credentials"
header, otherwise the request will be blocked.
2019-07-16 21:42:04 +00:00
Marshall Greenblatt
5e9ca096e0 Add support for GetAuthCredentials (fixes issue #2718, see issue #2622).
When NetworkService is enabled requests created using CefFrame::CreateURLRequest
will call CefRequestHandler::GetAuthCredentials for the associated browser after
calling CefURLRequestClient::GetAuthCredentials if that call returns false.
2019-07-16 13:30:46 -04:00
Marshall Greenblatt
3b211d4bf5 Remove POST data after redirect to GET (see issue #2707, see issue #2622).
For 303 redirects all request methods except HEAD are converted to GET as per
the latest http draft. For historical reasons the draft also allows POST
requests to be converted to GETs when following 301/302 redirects. Most major
browsers do this and so shall we. When a request is converted to GET any POST
data should also be removed.

Use 307 redirects instead if you want the request to be repeated using the same
method and POST data.
2019-07-11 16:43:39 -04:00
Marshall Greenblatt
2c92fcd3cd Fix cross-origin redirect from OnBeforeResourceLoad (fixes issue #2695, see issue #2622).
Modifying the URL in OnBeforeResourceLoad causes an internal redirect response.
In cases where the request is cross-origin (containing a non-null "Origin"
header) the redirect response must include the "Access-Control-Allow-Origin"
header, otherwise the request will be blocked.

This change also fixes a problem where existing request headers would be
discarded if the request was modified in OnBeforeResourceLoad.
2019-06-25 16:56:45 -04:00
Marshall Greenblatt
d792e5fddf Fix loading of http(s) sub-resources from custom scheme initiator (fixes issue #2685, see issue #2622).
Determine external request status based on the current URL instead of the
request initiator.
2019-06-25 11:04:15 -04:00
Marshall Greenblatt
f50b3c2d43 Fix CefFrame::GetIdentifier value in the render process (fixes issue #2687, see issue #2498) 2019-06-19 16:57:17 +02:00
Marshall Greenblatt
6ad1dea9fa Fix crash if a pending request is continued after deletion (see issue #2622).
This is a speculative fix for a crash where the pending ResourceRequest appears
to be invalid after the request is continued from SetInitialized.
2019-06-19 16:01:58 +02:00
Marshall Greenblatt
542c867901 Update to Chromium version 75.0.3770.100 2019-06-19 14:06:11 +02:00
Marshall Greenblatt
5da93a11c8 Fix crashes when a request is aborted during initialization (see issue #2622).
Initialization of request objects requires asynchronous hops between the UI and
IO threads. In some cases the browser may be destroyed, the mojo connection may
be aborted, or the ProxyURLLoaderFactory object may be deleted while
initialization is still in progress. This change fixes crashes and adds unit
tests that try to reproduce these conditions.

To test: Run `ceftests --gtest_repeat=50
              --gtest_filter=ResourceRequestHandlerTest.Basic*Abort*`
2019-06-18 16:31:53 +02:00
Marshall Greenblatt
19229b6d38 Fix crash in ProxyURLLoaderFactory::MaybeDestroySelf (see issue #2622).
This is a speculative fix for a crash where |on_disconnect_| appears to be null
in ProxyURLLoaderFactory::MaybeDestroySelf. The hypothesis here is that
OnURLLoaderClientError is being called while the proxy object is still in-flight
to ResourceContextData::AddProxy (e.g. before SetDisconnectCallback has been
called for the proxy object). Additonally, this change protects against
MaybeDestroySelf attempting to execute |on_disconnect_| multiple times.
2019-06-14 19:01:10 +02:00
Marshall Greenblatt
90ecd35aff Fix inclusion of cookies with restarted requests (fixes issue #2672, see issue #2622) 2019-06-12 17:21:12 +02:00
Marshall Greenblatt
d3b54cbec7 macOS: Don't disable custom libc++ for cef_sandbox build (see issue #2677) 2019-06-12 12:00:50 +02:00
Marshall Greenblatt
3f2a3b1c67 Use FrameTreeNodeId to find delay loaded iframes for OnBeforeBrowse (fixes issue #2675, see issue #2498) 2019-06-12 11:53:14 +02:00
Marshall Greenblatt
699a922bd4 Windows: cmake: Add newer VS versions 2019-06-11 18:08:48 +02:00
Marshall Greenblatt
3b2e46543b Windows: Disable custom libc++ for cef_sandbox build (fixes issue #2677) 2019-06-11 18:08:26 +02:00
Marshall Greenblatt
b5e74dd297 Update to Chromium version 75.0.3770.80 2019-06-08 23:06:25 +02:00
83 changed files with 2081 additions and 484 deletions

View File

@@ -407,6 +407,8 @@ static_library("libcef_static") {
"libcef/browser/net_service/cookie_helper.h",
"libcef/browser/net_service/cookie_manager_impl.cc",
"libcef/browser/net_service/cookie_manager_impl.h",
"libcef/browser/net_service/login_delegate.cc",
"libcef/browser/net_service/login_delegate.h",
"libcef/browser/net_service/proxy_url_loader_factory.cc",
"libcef/browser/net_service/proxy_url_loader_factory.h",
"libcef/browser/net_service/resource_handler_wrapper.cc",
@@ -596,6 +598,8 @@ static_library("libcef_static") {
"libcef/renderer/render_urlrequest_impl.cc",
"libcef/renderer/render_urlrequest_impl.h",
"libcef/renderer/thread_util.h",
"libcef/renderer/url_loader_throttle_provider_impl.cc",
"libcef/renderer/url_loader_throttle_provider_impl.h",
"libcef/renderer/v8_impl.cc",
"libcef/renderer/v8_impl.h",
"libcef/utility/content_utility_client.cc",

View File

@@ -7,5 +7,5 @@
# https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding
{
'chromium_checkout': 'refs/tags/75.0.3770.0'
'chromium_checkout': 'refs/tags/75.0.3770.100'
}

View File

@@ -374,6 +374,9 @@ if(OS_WINDOWS)
1913 # VS2017 version 15.6
1914 # VS2017 version 15.7
1915 # VS2017 version 15.8
1916 # VS2017 version 15.9
1920 # VS2019 version 16.0
1921 # VS2018 version 16.1
)
list(FIND supported_msvc_versions ${MSVC_VERSION} _index)
if (${_index} EQUAL -1)

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=59376c6298df4489ecc34f3509a8d0e77e9d97f7$
// $hash=fdfce3e4e33a1d4e1170497d2a476f0837994060$
//
#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_
@@ -238,6 +238,15 @@ typedef struct _cef_request_context_t {
struct _cef_request_context_t* self,
struct _cef_completion_callback_t* callback);
///
// Clears all HTTP authentication credentials that were added as part of
// handling GetAuthCredentials. If |callback| is non-NULL it will be executed
// on the UI thread after completion.
///
void(CEF_CALLBACK* clear_http_auth_credentials)(
struct _cef_request_context_t* self,
struct _cef_completion_callback_t* callback);
///
// Clears all active and idle connections that Chromium currently has. This is
// only recommended if you have released all other CEF objects but don't yet

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=fce8beb9d3e8709a512077681455cb4ef92ef76d$
// $hash=d9c4e8591ee39bd9d8c1714c0ca2417a7d2a38ea$
//
#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_HANDLER_CAPI_H_
@@ -154,10 +154,11 @@ typedef struct _cef_request_handler_t {
///
// Called on the IO thread when the browser needs credentials from the user.
// |isProxy| indicates whether the host is a proxy server. |host| contains the
// hostname and |port| contains the port number. |realm| is the realm of the
// challenge and may be NULL. |scheme| is the authentication scheme used, such
// as "basic" or "digest", and will be NULL if the source of the request is an
// |origin_url| is the origin making this authentication request. |isProxy|
// indicates whether the host is a proxy server. |host| contains the hostname
// and |port| contains the port number. |realm| is the realm of the challenge
// and may be NULL. |scheme| is the authentication scheme used, such as
// "basic" or "digest", and will be NULL if the source of the request is an
// FTP server. Return true (1) to continue the request and call
// cef_auth_callback_t::cont() either in this function or at a later time when
// the authentication information is available. Return false (0) to cancel the
@@ -166,7 +167,7 @@ typedef struct _cef_request_handler_t {
int(CEF_CALLBACK* get_auth_credentials)(
struct _cef_request_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_frame_t* frame,
const cef_string_t* origin_url,
int isProxy,
const cef_string_t* host,
int port,

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=f94ec1ef3928002394720160d526ed157282cc7a$
// $hash=8c6ffeab9c9183cc5f77929839643767ce5c5c2f$
//
#ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_HANDLER_CAPI_H_
@@ -151,9 +151,9 @@ typedef struct _cef_resource_handler_t {
///
// Skip response data when requested by a Range header. Skip over and discard
// |bytes_to_skip| bytes of response data. If data is available immediately
// set |bytes_skipped| to the number of of bytes skipped and return true (1).
// To read the data at a later time set |bytes_skipped| to 0, return true (1)
// and execute |callback| when the data is available. To indicate failure set
// set |bytes_skipped| to the number of bytes skipped and return true (1). To
// read the data at a later time set |bytes_skipped| to 0, return true (1) and
// execute |callback| when the data is available. To indicate failure set
// |bytes_skipped| to < 0 (e.g. -2 for ERR_FAILED) and return false (0). This
// function will be called in sequence but not from a dedicated thread.
///

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=af8ddd4d2d19e5b64d0a40778cb3c62fd5f1d8c9$
// $hash=adb3ca1e315a28efed7b2305c8aceb9c5eafdc66$
//
#ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_REQUEST_HANDLER_CAPI_H_
@@ -48,7 +48,6 @@
#include "include/capi/cef_resource_handler_capi.h"
#include "include/capi/cef_response_capi.h"
#include "include/capi/cef_response_filter_capi.h"
#include "include/internal/cef_types_wrappers.h"
#ifdef __cplusplus
extern "C" {

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=3d31b2d1bad50deeb68a5e6318344024c2f3f5be$
// $hash=77ac3a2aaea32b649185a58e4c2bbb13b7fe0540$
//
#ifndef CEF_INCLUDE_CAPI_CEF_URLREQUEST_CAPI_H_
@@ -193,9 +193,11 @@ typedef struct _cef_urlrequest_client_t {
// |isProxy| indicates whether the host is a proxy server. |host| contains the
// hostname and |port| contains the port number. Return true (1) to continue
// the request and call cef_auth_callback_t::cont() when the authentication
// information is available. Return false (0) to cancel the request. This
// function will only be called for requests initiated from the browser
// process.
// information is available. If the request has an associated browser/frame
// then returning false (0) will result in a call to GetAuthCredentials on the
// cef_request_tHandler associated with that browser, if any. Otherwise,
// returning false (0) will cancel the request immediately. This function will
// only be called for requests initiated from the browser process.
///
int(CEF_CALLBACK* get_auth_credentials)(
struct _cef_urlrequest_client_t* self,

View File

@@ -34,7 +34,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=0bc0d1faa22392b4245dc6eaf56337e7847a1900$
// $hash=467550bc7fb025b069edb9dc65988d8cb9c56fd2$
//
#ifndef CEF_INCLUDE_API_HASH_H_
@@ -47,13 +47,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "31b55dcbcf52e9f51fe423741f64e5c77e71c65a"
#define CEF_API_HASH_UNIVERSAL "3f2fd465a9dc95ef7d645c0b3c8bdf4e26d9b26e"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "afb8ea794d1bb0f56ba5ce1718a16e5dfd64229e"
#define CEF_API_HASH_PLATFORM "37fc3765fe0ef3ef7542e6568e5689b3575968a8"
#elif defined(OS_MACOSX)
#define CEF_API_HASH_PLATFORM "e3a279cf087095495c08fd9fa88daef5dbafff3a"
#define CEF_API_HASH_PLATFORM "dc61db096a4b62365b16d450fe4f898a9552da6a"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "d25833941c670d82cff0aa0ccf47b557d6813634"
#define CEF_API_HASH_PLATFORM "059d7243ae34aa5503c96a21ce24a673dddf4e64"
#endif
#ifdef __cplusplus

View File

@@ -249,6 +249,15 @@ class CefRequestContext : public virtual CefBaseRefCounted {
virtual void ClearCertificateExceptions(
CefRefPtr<CefCompletionCallback> callback) = 0;
///
// Clears all HTTP authentication credentials that were added as part of
// handling GetAuthCredentials. If |callback| is non-NULL it will be executed
// on the UI thread after completion.
///
/*--cef(optional_param=callback)--*/
virtual void ClearHttpAuthCredentials(
CefRefPtr<CefCompletionCallback> callback) = 0;
///
// Clears all active and idle connections that Chromium currently has.
// This is only recommended if you have released all other CEF objects but

View File

@@ -150,18 +150,19 @@ class CefRequestHandler : public virtual CefBaseRefCounted {
///
// Called on the IO thread when the browser needs credentials from the user.
// |isProxy| indicates whether the host is a proxy server. |host| contains the
// hostname and |port| contains the port number. |realm| is the realm of the
// challenge and may be empty. |scheme| is the authentication scheme used,
// such as "basic" or "digest", and will be empty if the source of the request
// is an FTP server. Return true to continue the request and call
// |origin_url| is the origin making this authentication request. |isProxy|
// indicates whether the host is a proxy server. |host| contains the hostname
// and |port| contains the port number. |realm| is the realm of the challenge
// and may be empty. |scheme| is the authentication scheme used, such as
// "basic" or "digest", and will be empty if the source of the request is an
// FTP server. Return true to continue the request and call
// CefAuthCallback::Continue() either in this method or at a later time when
// the authentication information is available. Return false to cancel the
// request immediately.
///
/*--cef(optional_param=realm,optional_param=scheme)--*/
virtual bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& origin_url,
bool isProxy,
const CefString& host,
int port,

View File

@@ -142,7 +142,7 @@ class CefResourceHandler : public virtual CefBaseRefCounted {
///
// Skip response data when requested by a Range header. Skip over and discard
// |bytes_to_skip| bytes of response data. If data is available immediately
// set |bytes_skipped| to the number of of bytes skipped and return true. To
// set |bytes_skipped| to the number of bytes skipped and return true. To
// read the data at a later time set |bytes_skipped| to 0, return true and
// execute |callback| when the data is available. To indicate failure set
// |bytes_skipped| to < 0 (e.g. -2 for ERR_FAILED) and return false. This

View File

@@ -46,7 +46,6 @@
#include "include/cef_resource_handler.h"
#include "include/cef_response.h"
#include "include/cef_response_filter.h"
#include "include/internal/cef_types_wrappers.h"
class CefCookieAccessFilter;

View File

@@ -186,8 +186,11 @@ class CefURLRequestClient : public virtual CefBaseRefCounted {
// |isProxy| indicates whether the host is a proxy server. |host| contains the
// hostname and |port| contains the port number. Return true to continue the
// request and call CefAuthCallback::Continue() when the authentication
// information is available. Return false to cancel the request. This method
// will only be called for requests initiated from the browser process.
// information is available. If the request has an associated browser/frame
// then returning false will result in a call to GetAuthCredentials on the
// CefRequestHandler associated with that browser, if any. Otherwise,
// returning false will cancel the request immediately. This method will only
// be called for requests initiated from the browser process.
///
/*--cef(optional_param=realm)--*/
virtual bool GetAuthCredentials(bool isProxy,

View File

@@ -220,7 +220,7 @@ typedef struct _cef_settings_t {
///
// The location where data for the global browser cache will be stored on
// disk. In non-empty this must be either equal to or a child directory of
// disk. If non-empty this must be either equal to or a child directory of
// CefSettings.root_cache_path. If empty then browsers will be created in
// "incognito mode" where in-memory caches are used for storage and no data is
// persisted to disk. HTML5 databases such as localStorage will only persist

View File

@@ -544,6 +544,7 @@ struct CefSettingsTraits {
cef_string_clear(&s->browser_subprocess_path);
cef_string_clear(&s->framework_dir_path);
cef_string_clear(&s->cache_path);
cef_string_clear(&s->root_cache_path);
cef_string_clear(&s->user_data_path);
cef_string_clear(&s->user_agent);
cef_string_clear(&s->product_version);
@@ -572,6 +573,8 @@ struct CefSettingsTraits {
cef_string_set(src->cache_path.str, src->cache_path.length,
&target->cache_path, copy);
cef_string_set(src->root_cache_path.str, src->root_cache_path.length,
&target->root_cache_path, copy);
cef_string_set(src->user_data_path.str, src->user_data_path.length,
&target->user_data_path, copy);
target->persist_session_cookies = src->persist_session_cookies;

View File

@@ -97,8 +97,9 @@ class CefScopedArgArray {
CefScopedArgArray(int argc, char* argv[]) {
// argv should have (argc + 1) elements, the last one always being NULL.
array_ = new char*[argc + 1];
values_.resize(argc);
for (int i = 0; i < argc; ++i) {
values_.push_back(argv[i]);
values_[i] = argv[i];
array_[i] = const_cast<char*>(values_[i].c_str());
}
array_[argc] = NULL;

View File

@@ -29,7 +29,7 @@ void CefAudioMirrorDestination::Start() {
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&content::AudioMirroringManager::StartMirroring,
base::Unretained(mirroring_manager_),
base::Unretained(this)));
base::RetainedRef(this)));
}
void CefAudioMirrorDestination::Stop() {
@@ -39,7 +39,7 @@ void CefAudioMirrorDestination::Stop() {
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&content::AudioMirroringManager::StopMirroring,
base::Unretained(mirroring_manager_),
base::Unretained(this)));
base::RetainedRef(this)));
}
// Asynchronously query whether this MirroringDestination wants to consume
@@ -56,7 +56,7 @@ void CefAudioMirrorDestination::QueryForMatches(
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&CefAudioMirrorDestination::QueryForMatchesOnUIThread,
base::Unretained(this), candidates,
base::RetainedRef(this), candidates,
media::BindToCurrentLoop(std::move(results_callback))));
}
@@ -99,7 +99,7 @@ media::AudioPushSink* CefAudioMirrorDestination::AddPushInput(
return new CefAudioPushSink(
params, browser_, cef_audio_handler_,
base::Bind(&CefAudioMirrorDestination::ReleasePushInput,
base::Unretained(this)));
base::RetainedRef(this)));
}
void CefAudioMirrorDestination::ReleasePushInput(CefAudioPushSink* sink) {

View File

@@ -22,14 +22,13 @@ class CefAudioPushSink;
class CefBrowserHostImpl;
class CefAudioMirrorDestination
: public content::AudioMirroringManager::MirroringDestination {
: public base::RefCountedThreadSafe<CefAudioMirrorDestination>,
public content::AudioMirroringManager::MirroringDestination {
public:
CefAudioMirrorDestination(CefRefPtr<CefBrowserHostImpl> browser,
CefRefPtr<CefAudioHandler> cef_audio_handler,
content::AudioMirroringManager* mirroring_manager);
virtual ~CefAudioMirrorDestination() = default;
// Start mirroring. This needs to be triggered on the IO thread.
void Start();
@@ -65,6 +64,10 @@ class CefAudioMirrorDestination
const media::AudioParameters& params) override;
private:
friend class base::RefCountedThreadSafe<CefAudioMirrorDestination>;
~CefAudioMirrorDestination() override = default;
void QueryForMatchesOnUIThread(
const std::set<content::GlobalFrameRoutingId>& candidates,
MatchesCallback results_callback);

View File

@@ -287,6 +287,10 @@ void CefBrowserContext::Initialize() {
CefString(&context->settings().accept_language_list);
}
if (!!settings_.persist_session_cookies) {
set_should_persist_session_cookies(true);
}
key_ = std::make_unique<ProfileKey>(GetPath());
SimpleKeyMap::GetInstance()->Associate(this, key_.get());

View File

@@ -183,6 +183,9 @@ class CefBrowserContext : public ChromeProfileStub,
// Values checked in ProfileNetworkContextService::CreateNetworkContextParams
// when creating the NetworkContext.
bool ShouldRestoreOldSessionCookies() override {
return should_persist_session_cookies_;
}
bool ShouldPersistSessionCookies() override {
return should_persist_session_cookies_;
}

View File

@@ -1576,6 +1576,11 @@ CefRefPtr<CefFrame> CefBrowserHostImpl::GetFrameForHost(
return browser_info_->GetFrameForHost(host);
}
CefRefPtr<CefFrame> CefBrowserHostImpl::GetFrameForFrameTreeNode(
int frame_tree_node_id) {
return browser_info_->GetFrameForFrameTreeNode(frame_tree_node_id, nullptr);
}
void CefBrowserHostImpl::LoadMainFrameURL(const std::string& url,
const content::Referrer& referrer,
ui::PageTransition transition,
@@ -2736,8 +2741,8 @@ bool CefBrowserHostImpl::StartAudioMirroring() {
if (client_.get()) {
CefRefPtr<CefAudioHandler> audio_handler = client_->GetAudioHandler();
if (audio_handler.get()) {
audio_mirror_destination_.reset(new CefAudioMirrorDestination(
this, audio_handler, content::AudioMirroringManager::GetInstance()));
audio_mirror_destination_ = new CefAudioMirrorDestination(
this, audio_handler, content::AudioMirroringManager::GetInstance());
audio_mirror_destination_->Start();
return true;
}

View File

@@ -299,6 +299,9 @@ class CefBrowserHostImpl : public CefBrowserHost,
// Returns the frame associated with the specified RenderFrameHost.
CefRefPtr<CefFrame> GetFrameForHost(const content::RenderFrameHost* host);
// Returns the frame associated with the specified FrameTreeNode ID.
CefRefPtr<CefFrame> GetFrameForFrameTreeNode(int frame_tree_node_id);
// Load the specified URL in the main frame.
void LoadMainFrameURL(const std::string& url,
const content::Referrer& referrer,
@@ -663,7 +666,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
bool is_background_host_ = false;
// Used to mirror audio streams
std::unique_ptr<CefAudioMirrorDestination> audio_mirror_destination_;
scoped_refptr<CefAudioMirrorDestination> audio_mirror_destination_;
// Used with auto-resize.
bool auto_resize_enabled_ = false;

View File

@@ -22,6 +22,7 @@
#include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/net/chrome_scheme_handler.h"
#include "libcef/browser/net/net_util.h"
#include "libcef/browser/net_service/login_delegate.h"
#include "libcef/browser/net_service/proxy_url_loader_factory.h"
#include "libcef/browser/net_service/resource_request_handler_wrapper.h"
#include "libcef/browser/plugins/plugin_service_filter.h"
@@ -108,6 +109,7 @@
#include "extensions/browser/io_thread_extension_message_filter.h"
#include "extensions/common/constants.h"
#include "extensions/common/switches.h"
#include "net/base/auth.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "ppapi/host/ppapi_host.h"
#include "services/network/public/cpp/network_switches.h"
@@ -429,6 +431,7 @@ bool NavigationOnUIThread(
bool is_main_frame,
int64_t frame_id,
int64_t parent_frame_id,
int frame_tree_node_id,
content::WebContents* source,
const navigation_interception::NavigationParams& params) {
CEF_REQUIRE_UIT();
@@ -447,7 +450,9 @@ bool NavigationOnUIThread(
frame = browser->GetMainFrame();
} else if (frame_id >= 0) {
frame = browser->GetFrame(frame_id);
DCHECK(frame);
}
if (!frame && frame_tree_node_id >= 0) {
frame = browser->GetFrameForFrameTreeNode(frame_tree_node_id);
}
if (!frame) {
// Create a temporary frame object for navigation of sub-frames that
@@ -1115,7 +1120,7 @@ CefContentBrowserClient::CreateThrottlesForNavigation(
std::make_unique<navigation_interception::InterceptNavigationThrottle>(
navigation_handle,
base::Bind(&NavigationOnUIThread, is_main_frame, frame_id,
parent_frame_id),
parent_frame_id, navigation_handle->GetFrameTreeNodeId()),
navigation_interception::SynchronyMode::kSync);
throttles.push_back(std::move(throttle));
@@ -1195,6 +1200,21 @@ CefContentBrowserClient::CreateClientCertStore(
->CreateClientCertStore();
}
std::unique_ptr<content::LoginDelegate>
CefContentBrowserClient::CreateLoginDelegate(
const net::AuthChallengeInfo& auth_info,
content::WebContents* web_contents,
const content::GlobalRequestID& request_id,
bool is_request_for_main_frame,
const GURL& url,
scoped_refptr<net::HttpResponseHeaders> response_headers,
bool first_auth_attempt,
LoginAuthRequiredCallback auth_required_callback) {
return std::make_unique<net_service::LoginDelegate>(
auth_info, web_contents, request_id, url,
std::move(auth_required_callback));
}
void CefContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
int frame_tree_node_id,
NonNetworkURLLoaderFactoryMap* factories) {

View File

@@ -150,10 +150,17 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
service_manager::BinderRegistry* registry,
blink::AssociatedInterfaceRegistry* associated_registry,
content::RenderProcessHost* render_process_host) override;
std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
content::ResourceContext* resource_context) override;
std::unique_ptr<content::LoginDelegate> CreateLoginDelegate(
const net::AuthChallengeInfo& auth_info,
content::WebContents* web_contents,
const content::GlobalRequestID& request_id,
bool is_request_for_main_frame,
const GURL& url,
scoped_refptr<net::HttpResponseHeaders> response_headers,
bool first_auth_attempt,
LoginAuthRequiredCallback auth_required_callback) override;
void RegisterNonNetworkNavigationURLLoaderFactories(
int frame_tree_node_id,
NonNetworkURLLoaderFactoryMap* factories) override;

View File

@@ -199,7 +199,7 @@ void CefExtensionSystem::Init() {
// mime_handler_private.idl), and returns the unique View ID via the
// |payload| argument.
// 5. The unique View ID arrives in the renderer process via
// ResourceLoader::didReceiveData and triggers creation of a new Document.
// ResourceLoader::DidReceiveData and triggers creation of a new Document.
// DOMImplementation::createDocument indirectly calls
// RendererBlinkPlatformImpl::getPluginList to retrieve the list of
// supported plugins from the browser process. If a plugin supports the

View File

@@ -26,8 +26,9 @@
(CefJavaScriptDialogRunner::DialogClosedCallback)callback;
- (NSAlert*)alert;
- (NSTextField*)textField;
- (void)alertDidEndWithResult:(NSModalResponse)returnCode
dialog:(CefJavaScriptDialogRunnerMac*)dialog;
- (void)alertDidEnd:(NSAlert*)alert
returnCode:(int)returnCode
contextInfo:(void*)contextInfo;
- (void)cancel;
@end
@@ -57,8 +58,9 @@
return textField_;
}
- (void)alertDidEndWithResult:(NSModalResponse)returnCode
dialog:(CefJavaScriptDialogRunnerMac*)dialog {
- (void)alertDidEnd:(NSAlert*)alert
returnCode:(int)returnCode
contextInfo:(void*)contextInfo {
if (returnCode == NSModalResponseStop)
return;
@@ -139,11 +141,16 @@ void CefJavaScriptDialogRunnerMac::Run(
// around the "callee requires a non-null argument" error that occurs when
// building with the 10.11 SDK. See http://crbug.com/383820 for related
// discussion.
// We can't use the newer beginSheetModalForWindow:completionHandler: variant
// because it fails silently when passed a nil argument (see issue #2726).
id nilArg = nil;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[alert beginSheetModalForWindow:nilArg // nil here makes it app-modal
completionHandler:^void(NSModalResponse returnCode) {
[helper_ alertDidEndWithResult:returnCode dialog:this];
}];
modalDelegate:helper_
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
contextInfo:this];
#pragma clang diagnostic pop
if ([alert accessoryView])
[[alert window] makeFirstResponder:[alert accessoryView]];

View File

@@ -395,13 +395,10 @@ net::NetworkDelegate::AuthRequiredResponse CefNetworkDelegate::OnAuthRequired(
if (client.get()) {
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
if (handler.get()) {
CefRefPtr<CefFrame> frame =
net_util::GetFrameForRequest(browser->browser_info(), request);
CefRefPtr<CefAuthCallbackImpl> callbackPtr(
new CefAuthCallbackImpl(std::move(callback), credentials));
if (handler->GetAuthCredentials(
browser.get(), frame, auth_info.is_proxy,
browser.get(), request->url().spec(), auth_info.is_proxy,
auth_info.challenger.host(), auth_info.challenger.port(),
auth_info.realm, auth_info.scheme, callbackPtr.get())) {
request->SetUserData(

View File

@@ -22,12 +22,88 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/render_frame_host.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
namespace {
const int32_t kInitialRequestID = -2;
// Request ID for requests initiated by CefBrowserURLRequest. request_ids
// generated by child processes are counted up from 0, while browser
// created requests start at -2 and go down from there. (We need to start at -2
// because -1 is used as a special value all over the resource_dispatcher_host
// for uninitialized variables.) The resource_dispatcher_host code path is not
// used when NetworkService is enabled so it's safe to repurpose the -2 and
// below range here.
// This method is only called on the UI thread.
int32_t MakeRequestID() {
static int32_t request_id = kInitialRequestID;
return --request_id;
}
// Manages the mapping of request IDs to request objects.
class RequestManager {
public:
RequestManager() {}
~RequestManager() { DCHECK(map_.empty()); }
void Add(int32_t request_id,
CefRefPtr<CefBrowserURLRequest> request,
CefRefPtr<CefURLRequestClient> client) {
DCHECK_LE(request_id, kInitialRequestID);
base::AutoLock lock_scope(lock_);
DCHECK(map_.find(request_id) == map_.end());
map_.insert(std::make_pair(request_id, std::make_pair(request, client)));
}
void Remove(int32_t request_id) {
if (request_id > kInitialRequestID)
return;
base::AutoLock lock_scope(lock_);
RequestMap::iterator it = map_.find(request_id);
DCHECK(it != map_.end());
map_.erase(it);
}
base::Optional<CefBrowserURLRequest::RequestInfo> Get(int32_t request_id) {
if (request_id > kInitialRequestID)
return base::nullopt;
base::AutoLock lock_scope(lock_);
RequestMap::const_iterator it = map_.find(request_id);
if (it != map_.end()) {
return it->second;
}
return base::nullopt;
}
private:
base::Lock lock_;
using RequestMap = std::map<int32_t, CefBrowserURLRequest::RequestInfo>;
RequestMap map_;
DISALLOW_COPY_AND_ASSIGN(RequestManager);
};
#if DCHECK_IS_ON()
// Because of DCHECK()s in the object destructor.
base::LazyInstance<RequestManager>::DestructorAtExit g_manager =
LAZY_INSTANCE_INITIALIZER;
#else
base::LazyInstance<RequestManager>::Leaky g_manager = LAZY_INSTANCE_INITIALIZER;
#endif
} // namespace
// CefBrowserURLRequest::Context ----------------------------------------------
class CefBrowserURLRequest::Context
@@ -113,6 +189,7 @@ class CefBrowserURLRequest::Context
request_context_impl->GetBrowserContext();
DCHECK(browser_context);
int render_frame_id = MSG_ROUTING_NONE;
scoped_refptr<net_service::URLLoaderFactoryGetter> loader_factory_getter;
if (frame) {
// The request will be associated with this frame/browser if it's valid,
@@ -120,6 +197,14 @@ class CefBrowserURLRequest::Context
content::RenderFrameHost* rfh =
static_cast<CefFrameHostImpl*>(frame.get())->GetRenderFrameHost();
if (rfh) {
// In cases where authentication is required this value will be passed
// as the |routing_id| parameter to
// NetworkServiceClient::OnAuthRequired. Despite the naming the
// GetWebContents method in network_service_client.cc expects it to be a
// FrameTreeNodeId. The |process_id| parameter will always be
// network::mojom::kBrowserProcessId (value 0) for these requests.
render_frame_id = rfh->GetFrameTreeNodeId();
loader_factory_getter =
net_service::URLLoaderFactoryGetter::Create(rfh, browser_context);
}
@@ -132,10 +217,12 @@ class CefBrowserURLRequest::Context
FROM_HERE,
base::BindOnce(
&CefBrowserURLRequest::Context::ContinueOnOriginatingThread, self,
loader_factory_getter));
render_frame_id, MakeRequestID(), loader_factory_getter));
}
void ContinueOnOriginatingThread(
int render_frame_id,
int32_t request_id,
scoped_refptr<net_service::URLLoaderFactoryGetter>
loader_factory_getter) {
DCHECK(CalledOnValidThread());
@@ -163,6 +250,8 @@ class CefBrowserURLRequest::Context
static_cast<CefRequestImpl*>(request_.get())
->Get(resource_request.get(), false);
resource_request->render_frame_id = render_frame_id;
// SimpleURLLoader is picky about the body contents. Try to populate them
// correctly below.
auto request_body = resource_request->request_body;
@@ -187,6 +276,11 @@ class CefBrowserURLRequest::Context
loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
NO_TRAFFIC_ANNOTATION_YET);
// Associate the request with |request_id|.
request_id_ = request_id;
loader_->SetRequestId(request_id);
g_manager.Get().Add(request_id, url_request_, client_);
if (request_body) {
if (request_body->elements()->size() == 1) {
const auto& element = (*request_body->elements())[0];
@@ -294,6 +388,7 @@ class CefBrowserURLRequest::Context
DCHECK(request_->GetFlags() | UR_FLAG_STOP_ON_REDIRECT);
response_->SetReadOnly(false);
response_->SetURL(redirect_info.new_url.spec());
response_->SetResponseHeaders(*response_head.headers);
response_->SetReadOnly(true);
@@ -403,6 +498,8 @@ class CefBrowserURLRequest::Context
DCHECK(CalledOnValidThread());
DCHECK(url_request_);
g_manager.Get().Remove(request_id_);
client_ = nullptr;
request_context_ = nullptr;
@@ -439,6 +536,8 @@ class CefBrowserURLRequest::Context
scoped_refptr<net_service::URLLoaderFactoryGetter> loader_factory_getter_;
std::unique_ptr<network::SimpleURLLoader> loader_;
int32_t request_id_ = 0;
CefURLRequest::Status status_ = UR_IO_PENDING;
CefRefPtr<CefResponseImpl> response_;
bool response_was_cached_ = false;
@@ -453,6 +552,22 @@ class CefBrowserURLRequest::Context
// CefBrowserURLRequest -------------------------------------------------------
// static
base::Optional<CefBrowserURLRequest::RequestInfo>
CefBrowserURLRequest::FromRequestID(int32_t request_id) {
return g_manager.Get().Get(request_id);
}
// static
base::Optional<CefBrowserURLRequest::RequestInfo>
CefBrowserURLRequest::FromRequestID(
const content::GlobalRequestID& request_id) {
if (request_id.child_id == network::mojom::kBrowserProcessId) {
return FromRequestID(request_id.request_id);
}
return base::nullopt;
}
CefBrowserURLRequest::CefBrowserURLRequest(
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,

View File

@@ -9,10 +9,28 @@
#include "include/cef_urlrequest.h"
#include "base/optional.h"
namespace content {
struct GlobalRequestID;
}
class CefBrowserURLRequest : public CefURLRequest {
public:
class Context;
// TODO(network): After the old network code path is deleted move the
// CefURLRequestClient::GetAuthCredentials callback to the context thread and
// return just the CefBrowserURLRequest object here. The *Client object can
// then be retrieved by calling GetClient() from the required thread.
using RequestInfo = std::pair<CefRefPtr<CefBrowserURLRequest>,
CefRefPtr<CefURLRequestClient>>;
// Retrieve the request objects, if any, associated with |request_id|.
static base::Optional<RequestInfo> FromRequestID(int32_t request_id);
static base::Optional<RequestInfo> FromRequestID(
const content::GlobalRequestID& request_id);
// If |frame| is nullptr requests can still be intercepted but no
// browser/frame will be associated with them.
CefBrowserURLRequest(CefRefPtr<CefFrame> frame,

View File

@@ -0,0 +1,172 @@
// Copyright (c) 2019 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/browser/net_service/login_delegate.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/net_service/browser_urlrequest_impl.h"
#include "libcef/browser/thread_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/web_contents.h"
namespace net_service {
namespace {
class AuthCallbackImpl : public CefAuthCallback {
public:
explicit AuthCallbackImpl(base::WeakPtr<LoginDelegate> delegate)
: delegate_(delegate),
task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
~AuthCallbackImpl() override {
if (delegate_.MaybeValid()) {
// If |delegate_| isn't valid this will be a no-op.
task_runner_->PostTask(FROM_HERE,
base::BindOnce(&LoginDelegate::Cancel, delegate_));
}
}
void Continue(const CefString& username, const CefString& password) override {
if (!task_runner_->RunsTasksInCurrentSequence()) {
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&AuthCallbackImpl::Continue, this, username,
password));
return;
}
if (delegate_) {
delegate_->Continue(username, password);
delegate_ = NULL;
}
}
void Cancel() override {
if (!task_runner_->RunsTasksInCurrentSequence()) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(&AuthCallbackImpl::Cancel, this));
return;
}
if (delegate_) {
delegate_->Cancel();
delegate_ = NULL;
}
}
private:
base::WeakPtr<LoginDelegate> delegate_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
IMPLEMENT_REFCOUNTING(AuthCallbackImpl);
DISALLOW_COPY_AND_ASSIGN(AuthCallbackImpl);
};
void RunCallbackOnIOThread(
CefRefPtr<CefBrowserHostImpl> browser,
base::Optional<CefBrowserURLRequest::RequestInfo> url_request_info,
const net::AuthChallengeInfo& auth_info,
const GURL& origin_url,
CefRefPtr<AuthCallbackImpl> callback_impl) {
CEF_REQUIRE_IOT();
// TODO(network): After the old network code path is deleted move this
// callback to the BrowserURLRequest's context thread.
if (url_request_info) {
bool handled = url_request_info->second->GetAuthCredentials(
auth_info.is_proxy, auth_info.challenger.host(),
auth_info.challenger.port(), auth_info.realm, auth_info.scheme,
callback_impl.get());
if (handled) {
// The user will execute the callback, or the request will be canceled on
// AuthCallbackImpl destruction.
return;
}
}
if (browser) {
CefRefPtr<CefClient> client = browser->GetClient();
if (client) {
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
if (handler) {
bool handled = handler->GetAuthCredentials(
browser.get(), origin_url.spec(), auth_info.is_proxy,
auth_info.challenger.host(), auth_info.challenger.port(),
auth_info.realm, auth_info.scheme, callback_impl.get());
if (handled) {
// The user will execute the callback, or the request will be canceled
// on AuthCallbackImpl destruction.
return;
}
}
}
}
callback_impl->Cancel();
}
} // namespace
LoginDelegate::LoginDelegate(const net::AuthChallengeInfo& auth_info,
content::WebContents* web_contents,
const content::GlobalRequestID& request_id,
const GURL& origin_url,
LoginAuthRequiredCallback callback)
: callback_(std::move(callback)), weak_ptr_factory_(this) {
CEF_REQUIRE_UIT();
// May be nullptr for requests originating from CefURLRequest.
CefRefPtr<CefBrowserHostImpl> browser;
if (web_contents) {
browser = CefBrowserHostImpl::GetBrowserForContents(web_contents);
}
// |callback| needs to be executed asynchronously.
CEF_POST_TASK(CEF_UIT, base::BindOnce(&LoginDelegate::Start,
weak_ptr_factory_.GetWeakPtr(), browser,
auth_info, request_id, origin_url));
}
void LoginDelegate::Continue(const CefString& username,
const CefString& password) {
CEF_REQUIRE_UIT();
if (!callback_.is_null()) {
std::move(callback_).Run(
net::AuthCredentials(username.ToString16(), password.ToString16()));
}
}
void LoginDelegate::Cancel() {
CEF_REQUIRE_UIT();
if (!callback_.is_null()) {
std::move(callback_).Run(base::nullopt);
}
}
void LoginDelegate::Start(CefRefPtr<CefBrowserHostImpl> browser,
const net::AuthChallengeInfo& auth_info,
const content::GlobalRequestID& request_id,
const GURL& origin_url) {
CEF_REQUIRE_UIT();
auto url_request_info = CefBrowserURLRequest::FromRequestID(request_id);
if (browser || url_request_info) {
// AuthCallbackImpl is bound to the current thread.
CefRefPtr<AuthCallbackImpl> callbackImpl =
new AuthCallbackImpl(weak_ptr_factory_.GetWeakPtr());
// Execute callbacks on the IO thread to maintain the "old"
// network_delegate callback behaviour.
CEF_POST_TASK(CEF_IOT, base::BindOnce(&RunCallbackOnIOThread, browser,
url_request_info, auth_info,
origin_url, callbackImpl));
} else {
Cancel();
}
}
} // namespace net_service

View File

@@ -0,0 +1,50 @@
// Copyright (c) 2019 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_BROWSER_NET_SERVICE_LOGIN_DELEGATE_H_
#define CEF_LIBCEF_BROWSER_NET_SERVICE_LOGIN_DELEGATE_H_
#include "include/cef_base.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/login_delegate.h"
#include "net/base/auth.h"
namespace content {
struct GlobalRequestID;
class WebContents;
} // namespace content
class CefBrowserHostImpl;
class GURL;
namespace net_service {
class LoginDelegate : public content::LoginDelegate {
public:
// This object will be deleted when |callback| is executed or the request is
// canceled. |callback| should not be executed after this object is deleted.
LoginDelegate(const net::AuthChallengeInfo& auth_info,
content::WebContents* web_contents,
const content::GlobalRequestID& request_id,
const GURL& origin_url,
LoginAuthRequiredCallback callback);
void Continue(const CefString& username, const CefString& password);
void Cancel();
private:
void Start(CefRefPtr<CefBrowserHostImpl> browser,
const net::AuthChallengeInfo& auth_info,
const content::GlobalRequestID& request_id,
const GURL& origin_url);
LoginAuthRequiredCallback callback_;
base::WeakPtrFactory<LoginDelegate> weak_ptr_factory_;
};
} // namespace net_service
#endif // CEF_LIBCEF_BROWSER_NET_SERVICE_LOGIN_DELEGATE_H_

View File

@@ -17,6 +17,7 @@
#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/cors/cors.h"
namespace net_service {
@@ -40,7 +41,14 @@ class ResourceContextData : public base::SupportsUserData::Data {
CEF_REQUIRE_UIT();
content::WebContents* web_contents = web_contents_getter.Run();
DCHECK(web_contents);
// Maybe the browser was destroyed while AddProxyOnUIThread was pending.
if (!web_contents) {
// Delete on the IO thread as expected by mojo bindings.
content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
proxy);
return;
}
content::BrowserContext* browser_context =
web_contents->GetBrowserContext();
@@ -59,6 +67,12 @@ class ResourceContextData : public base::SupportsUserData::Data {
content::ResourceContext* resource_context) {
CEF_REQUIRE_IOT();
// Maybe the proxy was destroyed while AddProxyOnUIThread was pending.
if (proxy->destroyed_) {
delete proxy;
return;
}
auto* self = static_cast<ResourceContextData*>(
resource_context->GetUserData(kResourceContextUserDataKey));
if (!self) {
@@ -595,12 +609,6 @@ void InterceptedRequest::BeforeRequestReceived(const GURL& original_url,
// Equivalent to no interception.
InterceptResponseReceived(original_url, nullptr);
} else {
if (request_.referrer.is_valid()) {
// Intentionally override if referrer header already exists.
request_.headers.SetHeader(net::HttpRequestHeaders::kReferer,
request_.referrer.spec());
}
// TODO(network): Verify the case when WebContents::RenderFrameDeleted is
// called before network request is intercepted (i.e. if that's possible
// and whether it can result in any issues).
@@ -629,6 +637,20 @@ void InterceptedRequest::InterceptResponseReceived(
head.encoded_data_length = head.headers->raw_headers().length();
head.content_length = head.encoded_body_length = 0;
std::string origin;
if (request_.headers.GetHeader(net::HttpRequestHeaders::kOrigin, &origin) &&
origin != url::Origin().Serialize()) {
// Allow redirects of cross-origin resource loads.
head.headers->AddHeader(MakeHeader(
network::cors::header_names::kAccessControlAllowOrigin, origin));
}
if (request_.fetch_credentials_mode ==
network::mojom::FetchCredentialsMode::kInclude) {
head.headers->AddHeader(MakeHeader(
network::cors::header_names::kAccessControlAllowCredentials, "true"));
}
current_response_ = head;
const net::RedirectInfo& redirect_info =
MakeRedirectInfo(request_, head.headers.get(), request_.url, 0);
@@ -815,6 +837,11 @@ void InterceptedRequest::ContinueToBeforeRedirect(
request_.site_for_cookies = redirect_info.new_site_for_cookies;
request_.referrer = GURL(redirect_info.new_referrer);
request_.referrer_policy = redirect_info.new_referrer_policy;
// The request method can be changed to "GET". In this case we need to
// reset the request body manually.
if (request_.method == net::HttpRequestHeaders::kGetMethod)
request_.request_body = nullptr;
}
void InterceptedRequest::ContinueToResponseStarted(int error_code) {
@@ -862,6 +889,9 @@ void InterceptedRequest::ContinueToResponseStarted(int error_code) {
}
void InterceptedRequest::OnDestroy() {
// We don't want any callbacks after this point.
weak_factory_.InvalidateWeakPtrs();
factory_->request_handler_->OnRequestComplete(id_, request_, status_);
// Destroys |this|.
@@ -1027,7 +1057,9 @@ ProxyURLLoaderFactory::ProxyURLLoaderFactory(
url_loader_header_client_binding_.Bind(std::move(header_client_request));
}
ProxyURLLoaderFactory::~ProxyURLLoaderFactory() {}
ProxyURLLoaderFactory::~ProxyURLLoaderFactory() {
CEF_REQUIRE_IOT();
}
// static
void ProxyURLLoaderFactory::CreateOnIOThread(
@@ -1046,6 +1078,7 @@ void ProxyURLLoaderFactory::CreateOnIOThread(
void ProxyURLLoaderFactory::SetDisconnectCallback(
DisconnectCallback on_disconnect) {
CEF_REQUIRE_IOT();
DCHECK(!destroyed_);
DCHECK(!on_disconnect_);
on_disconnect_ = std::move(on_disconnect);
}
@@ -1179,8 +1212,14 @@ void ProxyURLLoaderFactory::MaybeDestroySelf() {
if (target_factory_.is_bound() || !requests_.empty())
return;
// Deletes |this|.
std::move(on_disconnect_).Run(this);
CHECK(!destroyed_);
destroyed_ = true;
// In some cases we may be destroyed before SetDisconnectCallback is called.
if (on_disconnect_) {
// Deletes |this|.
std::move(on_disconnect_).Run(this);
}
}
} // namespace net_service

View File

@@ -195,6 +195,7 @@ class ProxyURLLoaderFactory
std::unique_ptr<InterceptedRequestHandler> request_handler_;
bool destroyed_ = false;
DisconnectCallback on_disconnect_;
// Map of request ID to request object.

View File

@@ -36,6 +36,9 @@ namespace net_service {
namespace {
const int kLoadNoCookiesFlags =
net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
class RequestCallbackWrapper : public CefRequestCallback {
public:
using Callback = base::OnceCallback<void(bool /* allow */)>;
@@ -163,7 +166,32 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
class DestructionObserver : public CefBrowserHostImpl::Observer,
public CefContext::Observer {
public:
DestructionObserver() = default;
explicit DestructionObserver(CefBrowserHostImpl* browser) {
if (browser) {
browser_info_ = browser->browser_info();
browser->AddObserver(this);
} else {
CefContext::Get()->AddObserver(this);
}
}
virtual ~DestructionObserver() {
CEF_REQUIRE_UIT();
if (!registered_)
return;
// Verify that the browser or context still exists before attempting to
// remove the observer.
if (browser_info_) {
auto browser = browser_info_->browser();
if (browser)
browser->RemoveObserver(this);
} else if (CefContext::Get()) {
// Network requests may be torn down during shutdown, so we can't check
// CONTEXT_STATE_VALID() here.
CefContext::Get()->RemoveObserver(this);
}
}
void SetWrapper(base::WeakPtr<InterceptedRequestHandlerWrapper> wrapper) {
CEF_REQUIRE_IOT();
@@ -173,121 +201,190 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
void OnBrowserDestroyed(CefBrowserHostImpl* browser) override {
CEF_REQUIRE_UIT();
browser->RemoveObserver(this);
registered_ = false;
browser_info_ = nullptr;
NotifyOnDestroyed();
}
void OnContextDestroyed() override {
CEF_REQUIRE_UIT();
CefContext::Get()->RemoveObserver(this);
registered_ = false;
NotifyOnDestroyed();
}
private:
void NotifyOnDestroyed() {
// It's not safe to test the WeakPtr on the UI thread, so we'll just post
// a task which will be ignored if the WeakPtr is invalid.
CEF_POST_TASK(CEF_IOT, base::BindOnce(
&InterceptedRequestHandlerWrapper::OnDestroyed,
wrapper_));
if (wrapper_.MaybeValid()) {
// This will be a no-op if the WeakPtr is invalid.
CEF_POST_TASK(
CEF_IOT,
base::BindOnce(&InterceptedRequestHandlerWrapper::OnDestroyed,
wrapper_));
}
}
scoped_refptr<CefBrowserInfo> browser_info_;
bool registered_ = true;
base::WeakPtr<InterceptedRequestHandlerWrapper> wrapper_;
DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
};
InterceptedRequestHandlerWrapper() : weak_ptr_factory_(this) {}
// Holds state information for InterceptedRequestHandlerWrapper. State is
// initialized on the UI thread and later passed to the *Wrapper object on
// the IO thread.
struct InitState {
InitState() {}
~InterceptedRequestHandlerWrapper() override {
// There should be no pending or in-progress requests during destruction.
DCHECK(pending_requests_.empty());
DCHECK(request_map_.empty());
~InitState() {
if (destruction_observer_) {
if (initialized_) {
// Clear the reference added in
// InterceptedRequestHandlerWrapper::SetInitialized().
destruction_observer_->SetWrapper(nullptr);
}
DeleteDestructionObserver();
}
}
if (destruction_observer_) {
destruction_observer_->SetWrapper(nullptr);
void Initialize(content::BrowserContext* browser_context,
CefRefPtr<CefBrowserHostImpl> browser,
CefRefPtr<CefFrame> frame,
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool is_navigation,
bool is_download,
const url::Origin& request_initiator) {
CEF_REQUIRE_UIT();
browser_context_ = browser_context;
resource_context_ = static_cast<CefResourceContext*>(
browser_context->GetResourceContext());
DCHECK(resource_context_);
// We register to be notified of CEF context or browser destruction so
// that we can stop accepting new requests and cancel pending/in-progress
// requests in a timely manner (e.g. before we start asserting about
// leaked objects during CEF shutdown).
destruction_observer_.reset(new DestructionObserver(browser.get()));
if (browser) {
// These references will be released in OnDestroyed().
browser_ = browser;
frame_ = frame;
}
render_process_id_ = render_process_id;
render_frame_id_ = render_frame_id;
frame_tree_node_id_ = frame_tree_node_id;
is_navigation_ = is_navigation;
is_download_ = is_download;
request_initiator_ = request_initiator.Serialize();
// Default values for standard headers.
accept_language_ = ComputeAcceptLanguageFromPref(
GetAcceptLanguageList(browser_context, browser));
DCHECK(!accept_language_.empty());
user_agent_ = CefContentClient::Get()->browser()->GetUserAgent();
DCHECK(!user_agent_.empty());
}
void DeleteDestructionObserver() {
DCHECK(destruction_observer_);
CEF_POST_TASK(
CEF_UIT, base::BindOnce(&InterceptedRequestHandlerWrapper::
RemoveDestructionObserverOnUIThread,
browser_ ? browser_->browser_info() : nullptr,
std::move(destruction_observer_)));
}
}
static void RemoveDestructionObserverOnUIThread(
scoped_refptr<CefBrowserInfo> browser_info,
std::unique_ptr<DestructionObserver> observer) {
// Verify that the browser or context is still valid before attempting to
// remove the observer.
if (browser_info) {
auto browser = browser_info->browser();
if (browser)
browser->RemoveObserver(observer.get());
} else if (CONTEXT_STATE_VALID()) {
CefContext::Get()->RemoveObserver(observer.get());
}
}
void Initialize(content::BrowserContext* browser_context,
CefRefPtr<CefBrowserHostImpl> browser,
CefRefPtr<CefFrame> frame,
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool is_navigation,
bool is_download,
const url::Origin& request_initiator,
bool is_external) {
CEF_REQUIRE_UIT();
browser_context_ = browser_context;
resource_context_ =
static_cast<CefResourceContext*>(browser_context->GetResourceContext());
DCHECK(resource_context_);
// We register to be notified of CEF context or browser destruction so that
// we can stop accepting new requests and cancel pending/in-progress
// requests in a timely manner (e.g. before we start asserting about leaked
// objects during CEF shutdown).
destruction_observer_.reset(new DestructionObserver());
if (browser) {
// These references will be released in OnDestroyed().
browser_ = browser;
frame_ = frame;
browser->AddObserver(destruction_observer_.get());
} else {
CefContext::Get()->AddObserver(destruction_observer_.get());
CEF_UIT,
base::BindOnce(&InitState::DeleteDestructionObserverOnUIThread,
std::move(destruction_observer_)));
}
render_process_id_ = render_process_id;
render_frame_id_ = render_frame_id;
frame_tree_node_id_ = frame_tree_node_id;
is_navigation_ = is_navigation;
is_download_ = is_download;
request_initiator_ = request_initiator.Serialize();
is_external_ = is_external;
static void DeleteDestructionObserverOnUIThread(
std::unique_ptr<DestructionObserver> observer) {}
// Only accessed on the UI thread.
content::BrowserContext* browser_context_ = nullptr;
bool initialized_ = false;
CefRefPtr<CefBrowserHostImpl> browser_;
CefRefPtr<CefFrame> frame_;
CefResourceContext* resource_context_ = nullptr;
int render_process_id_ = 0;
int render_frame_id_ = -1;
int frame_tree_node_id_ = -1;
bool is_navigation_ = true;
bool is_download_ = false;
CefString request_initiator_;
// Default values for standard headers.
accept_language_ = ComputeAcceptLanguageFromPref(
GetAcceptLanguageList(browser_context, browser));
DCHECK(!accept_language_.empty());
user_agent_ = CefContentClient::Get()->browser()->GetUserAgent();
DCHECK(!user_agent_.empty());
std::string accept_language_;
std::string user_agent_;
CEF_POST_TASK(
CEF_IOT,
base::BindOnce(&InterceptedRequestHandlerWrapper::SetInitialized,
weak_ptr_factory_.GetWeakPtr()));
// Used to receive destruction notification.
std::unique_ptr<DestructionObserver> destruction_observer_;
};
// Manages InterceptedRequestHandlerWrapper initialization. The *Wrapper
// object is owned by ProxyURLLoaderFactory and may be deleted before
// SetInitialized() is called.
struct InitHelper : base::RefCountedThreadSafe<InitHelper> {
public:
explicit InitHelper(InterceptedRequestHandlerWrapper* wrapper)
: wrapper_(wrapper) {}
void MaybeSetInitialized(std::unique_ptr<InitState> init_state) {
CEF_POST_TASK(CEF_IOT, base::BindOnce(&InitHelper::SetInitialized, this,
std::move(init_state)));
}
void Disconnect() {
base::AutoLock lock_scope(lock_);
wrapper_ = nullptr;
}
private:
void SetInitialized(std::unique_ptr<InitState> init_state) {
base::AutoLock lock_scope(lock_);
// May be nullptr if the InterceptedRequestHandlerWrapper has already
// been deleted.
if (!wrapper_)
return;
wrapper_->SetInitialized(std::move(init_state));
wrapper_ = nullptr;
}
base::Lock lock_;
InterceptedRequestHandlerWrapper* wrapper_;
};
InterceptedRequestHandlerWrapper()
: init_helper_(base::MakeRefCounted<InitHelper>(this)),
weak_ptr_factory_(this) {}
~InterceptedRequestHandlerWrapper() override {
CEF_REQUIRE_IOT();
// There should be no in-progress requests during destruction.
DCHECK(request_map_.empty());
// Don't continue with initialization if we get deleted before
// SetInitialized is called asynchronously.
init_helper_->Disconnect();
}
void SetInitialized() {
scoped_refptr<InitHelper> init_helper() const { return init_helper_; }
void SetInitialized(std::unique_ptr<InitState> init_state) {
CEF_REQUIRE_IOT();
initialized_ = true;
DCHECK(!init_state_);
init_state_ = std::move(init_state);
// Check that the CEF context or associated browser was not destroyed
// between the calls to Initialize and SetInitialized, in which case
// we won't get an OnDestroyed callback from DestructionObserver.
if (browser_) {
if (!browser_->browser_info()->browser()) {
if (init_state_->browser_) {
if (!init_state_->browser_->browser_info()->browser()) {
OnDestroyed();
return;
}
@@ -296,7 +393,9 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
return;
}
destruction_observer_->SetWrapper(weak_ptr_factory_.GetWeakPtr());
init_state_->initialized_ = true;
init_state_->destruction_observer_->SetWrapper(
weak_ptr_factory_.GetWeakPtr());
// Continue any pending requests.
if (!pending_requests_.empty()) {
@@ -320,7 +419,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
return;
}
if (!initialized_) {
if (!init_state_) {
// Queue requests until we're initialized.
pending_requests_.push_back(std::make_unique<PendingRequest>(
id, request, request_was_redirected, std::move(callback),
@@ -333,19 +432,22 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
// Add standard headers, if currently unspecified.
request->headers.SetHeaderIfMissing(
net::HttpRequestHeaders::kAcceptLanguage, accept_language_);
net::HttpRequestHeaders::kAcceptLanguage,
init_state_->accept_language_);
request->headers.SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent,
user_agent_);
init_state_->user_agent_);
const bool is_external = IsExternalRequest(request);
// External requests will not have a default handler.
bool intercept_only = is_external_;
bool intercept_only = is_external;
CefRefPtr<CefRequestImpl> requestPtr;
CefRefPtr<CefResourceRequestHandler> handler =
GetHandler(id, request, &intercept_only, requestPtr);
CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
resource_context_->GetSchemeHandlerFactory(request->url);
init_state_->resource_context_->GetSchemeHandlerFactory(request->url);
if (scheme_factory && !requestPtr) {
requestPtr = MakeRequest(request, id.hash(), true);
}
@@ -360,13 +462,13 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
std::move(cancel_callback));
if (handler) {
state->cookie_filter_ =
handler->GetCookieAccessFilter(browser_, frame_, requestPtr.get());
state->cookie_filter_ = handler->GetCookieAccessFilter(
init_state_->browser_, init_state_->frame_, requestPtr.get());
}
auto exec_callback =
base::BindOnce(std::move(callback), maybe_intercept_request,
is_external_ ? true : intercept_only);
is_external ? true : intercept_only);
if (!maybe_intercept_request) {
// Cookies will be handled by the NetworkService.
@@ -395,7 +497,8 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
auto done_cookie_callback = base::BindOnce(
&InterceptedRequestHandlerWrapper::ContinueWithLoadedCookies,
weak_ptr_factory_.GetWeakPtr(), id, request, std::move(callback));
net_service::LoadCookies(browser_context_, *request, allow_cookie_callback,
net_service::LoadCookies(init_state_->browser_context_, *request,
allow_cookie_callback,
std::move(done_cookie_callback));
}
@@ -421,7 +524,8 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
CefCookie cef_cookie;
if (net_service::MakeCefCookie(cookie, cef_cookie)) {
*allow = state->cookie_filter_->CanSendCookie(
browser_, frame_, state->pending_request_.get(), cef_cookie);
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), cef_cookie);
}
}
@@ -443,8 +547,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
// Also add/save cookies ourselves for default-handled network requests
// so that we can filter them. This will be a no-op for custom-handled
// requests.
request->load_flags |=
net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
request->load_flags |= kLoadNoCookiesFlags;
}
if (!allowed_cookies.empty()) {
@@ -490,7 +593,8 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
base::Passed(std::move(callback))));
cef_return_value_t retval = state->handler_->OnBeforeResourceLoad(
browser_, frame_, state->pending_request_.get(), callbackPtr.get());
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), callbackPtr.get());
if (retval != RV_CONTINUE_ASYNC) {
// Continue or cancel the request immediately.
callbackPtr->Continue(retval == RV_CONTINUE);
@@ -555,12 +659,13 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
if (state->handler_) {
// Does the client want to handle the request?
resource_handler = state->handler_->GetResourceHandler(
browser_, frame_, state->pending_request_.get());
init_state_->browser_, init_state_->frame_,
state->pending_request_.get());
}
if (!resource_handler && state->scheme_factory_) {
// Does the scheme factory want to handle the request?
resource_handler = state->scheme_factory_->Create(
browser_, frame_, request->url.scheme(),
init_state_->browser_, init_state_->frame_, request->url.scheme(),
state->pending_request_.get());
}
@@ -615,6 +720,11 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
return;
}
if (state->cookie_filter_) {
// Remove the flags that were added in ContinueWithLoadedCookies.
request->load_flags &= ~kLoadNoCookiesFlags;
}
if (!state->handler_) {
// Cookies may come from a scheme handler.
MaybeSaveCookies(
@@ -646,9 +756,9 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
CefString newUrl = redirect_info.new_url.spec();
CefString oldUrl = newUrl;
bool url_changed = false;
state->handler_->OnResourceRedirect(browser_, frame_,
state->pending_request_.get(),
state->pending_response_.get(), newUrl);
state->handler_->OnResourceRedirect(
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), state->pending_response_.get(), newUrl);
if (newUrl != oldUrl) {
// Also support relative URLs.
const GURL& url = redirect_info.new_url.Resolve(newUrl.ToString());
@@ -684,9 +794,9 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
auto response_mode = ResponseMode::CONTINUE;
GURL new_url;
if (state->handler_->OnResourceResponse(browser_, frame_,
state->pending_request_.get(),
state->pending_response_.get())) {
if (state->handler_->OnResourceResponse(
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), state->pending_response_.get())) {
// The request may have been modified.
const auto changes = state->pending_request_->GetChanges();
if (changes) {
@@ -746,7 +856,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
auto done_cookie_callback = base::BindOnce(
&InterceptedRequestHandlerWrapper::ContinueWithSavedCookies,
weak_ptr_factory_.GetWeakPtr(), id, std::move(callback));
net_service::SaveCookies(browser_context_, *request, head,
net_service::SaveCookies(init_state_->browser_context_, *request, head,
allow_cookie_callback,
std::move(done_cookie_callback));
}
@@ -768,8 +878,9 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
CefCookie cef_cookie;
if (net_service::MakeCefCookie(cookie, cef_cookie)) {
*allow = state->cookie_filter_->CanSaveCookie(
browser_, frame_, state->pending_request_.get(),
state->pending_response_.get(), cef_cookie);
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), state->pending_response_.get(),
cef_cookie);
}
}
@@ -795,8 +906,8 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
if (state->handler_) {
auto filter = state->handler_->GetResourceResponseFilter(
browser_, frame_, state->pending_request_.get(),
state->pending_response_.get());
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), state->pending_response_.get());
if (filter) {
return CreateResponseFilterHandler(
filter, std::move(body),
@@ -831,14 +942,28 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
RequestState* state = GetState(id);
if (!state) {
// The request may have been canceled during destruction.
// The request may have been aborted during initialization or canceled
// during destruction. This method will always be called before a request
// is deleted, so if the request is currently pending also remove it from
// the list.
if (!pending_requests_.empty()) {
PendingRequests::iterator it = pending_requests_.begin();
for (; it != pending_requests_.end(); ++it) {
if ((*it)->id_ == id) {
pending_requests_.erase(it);
break;
}
}
}
return;
}
const bool is_external = IsExternalRequest(&request);
// Redirection of standard custom schemes is handled with a restart, so we
// get completion notifications for both the original (redirected) request
// and the final request. Don't report completion of the redirected request.
const bool ignore_result = is_external_ && request.url.IsStandard() &&
const bool ignore_result = is_external && request.url.IsStandard() &&
status.error_code == net::ERR_ABORTED &&
state->pending_response_.get() &&
net::HttpResponseHeaders::IsRedirectResponseCode(
@@ -849,11 +974,11 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
CallHandlerOnComplete(state, status);
if (status.error_code != 0 && is_external_) {
if (status.error_code != 0 && is_external) {
bool allow_os_execution = false;
state->handler_->OnProtocolExecution(browser_, frame_,
state->pending_request_.get(),
allow_os_execution);
state->handler_->OnProtocolExecution(
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), allow_os_execution);
if (allow_os_execution) {
CefBrowserPlatformDelegate::HandleExternalProtocol(request.url);
}
@@ -886,8 +1011,8 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
state->pending_response_->SetReadOnly(true);
state->handler_->OnResourceLoadComplete(
browser_, frame_, state->pending_request_.get(),
state->pending_response_.get(),
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), state->pending_response_.get(),
status.error_code == 0 ? UR_SUCCESS : UR_FAILED,
status.encoded_body_length);
}
@@ -902,9 +1027,10 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
const int64 request_id = id.hash();
if (browser_) {
if (init_state_->browser_) {
// Maybe the browser's client wants to handle it?
CefRefPtr<CefClient> client = browser_->GetHost()->GetClient();
CefRefPtr<CefClient> client =
init_state_->browser_->GetHost()->GetClient();
if (client) {
CefRefPtr<CefRequestHandler> request_handler =
client->GetRequestHandler();
@@ -912,8 +1038,9 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
requestPtr = MakeRequest(request, request_id, true);
handler = request_handler->GetResourceRequestHandler(
browser_, frame_, requestPtr.get(), is_navigation_, is_download_,
request_initiator_, *intercept_only);
init_state_->browser_, init_state_->frame_, requestPtr.get(),
init_state_->is_navigation_, init_state_->is_download_,
init_state_->request_initiator_, *intercept_only);
}
}
}
@@ -921,16 +1048,17 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
if (!handler) {
// Maybe the request context wants to handle it?
CefRefPtr<CefRequestContextHandler> context_handler =
resource_context_->GetHandler(render_process_id_,
request->render_frame_id,
frame_tree_node_id_, false);
init_state_->resource_context_->GetHandler(
init_state_->render_process_id_, request->render_frame_id,
init_state_->frame_tree_node_id_, false);
if (context_handler) {
if (!requestPtr)
requestPtr = MakeRequest(request, request_id, true);
handler = context_handler->GetResourceRequestHandler(
browser_, frame_, requestPtr.get(), is_navigation_, is_download_,
request_initiator_, *intercept_only);
init_state_->browser_, init_state_->frame_, requestPtr.get(),
init_state_->is_navigation_, init_state_->is_download_,
init_state_->request_initiator_, *intercept_only);
}
}
@@ -964,10 +1092,9 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
// CEF context or associated browser is destroyed.
void OnDestroyed() {
CEF_REQUIRE_IOT();
DCHECK(initialized_);
DCHECK(init_state_);
DCHECK(destruction_observer_);
destruction_observer_.reset();
init_state_->DeleteDestructionObserver();
// Stop accepting new requests.
shutting_down_ = true;
@@ -990,10 +1117,10 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
network::URLLoaderCompletionStatus(net::ERR_ABORTED));
}
if (browser_) {
if (init_state_->browser_) {
// Clear objects that reference the browser.
browser_ = nullptr;
frame_ = nullptr;
init_state_->browser_ = nullptr;
init_state_->frame_ = nullptr;
}
// Execute cancel callbacks and delete pending and in-progress requests.
@@ -1023,43 +1150,29 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
return requestPtr;
}
bool initialized_ = false;
// Returns true if |request| cannot be handled internally.
static bool IsExternalRequest(const network::ResourceRequest* request) {
return !scheme::IsInternalHandledScheme(request->url.scheme());
}
scoped_refptr<InitHelper> init_helper_;
std::unique_ptr<InitState> init_state_;
bool shutting_down_ = false;
// Only accessed on the UI thread.
content::BrowserContext* browser_context_ = nullptr;
CefRefPtr<CefBrowserHostImpl> browser_;
CefRefPtr<CefFrame> frame_;
CefResourceContext* resource_context_ = nullptr;
int render_process_id_ = 0;
int render_frame_id_ = -1;
int frame_tree_node_id_ = -1;
bool is_navigation_ = true;
bool is_download_ = false;
CefString request_initiator_;
bool is_external_ = false;
// Default values for standard headers.
std::string accept_language_;
std::string user_agent_;
using RequestMap = std::map<RequestId, std::unique_ptr<RequestState>>;
RequestMap request_map_;
using PendingRequests = std::vector<std::unique_ptr<PendingRequest>>;
PendingRequests pending_requests_;
// Used to receive destruction notification.
std::unique_ptr<DestructionObserver> destruction_observer_;
base::WeakPtrFactory<InterceptedRequestHandlerWrapper> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(InterceptedRequestHandlerWrapper);
};
void InitOnUIThread(
InterceptedRequestHandlerWrapper* wrapper,
scoped_refptr<InterceptedRequestHandlerWrapper::InitHelper> init_helper,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
int frame_tree_node_id,
const network::ResourceRequest& request) {
@@ -1116,6 +1229,7 @@ void InitOnUIThread(
}
#endif
// May return nullptr for requests originating from guest views.
browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame);
if (browserPtr) {
framePtr = browserPtr->GetFrameForHost(frame);
@@ -1133,10 +1247,14 @@ void InitOnUIThread(
if (request.request_initiator.has_value())
request_initiator = *request.request_initiator;
wrapper->Initialize(browser_context, browserPtr, framePtr, render_process_id,
request.render_frame_id, frame_tree_node_id,
is_navigation, is_download, request_initiator,
true /* is_external */);
auto init_state =
std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
init_state->Initialize(browser_context, browserPtr, framePtr,
render_process_id, request.render_frame_id,
frame_tree_node_id, is_navigation, is_download,
request_initiator);
init_helper->MaybeSetInitialized(std::move(init_state));
}
} // namespace
@@ -1149,8 +1267,6 @@ std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
bool is_download,
const url::Origin& request_initiator) {
CEF_REQUIRE_UIT();
auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
CefRefPtr<CefBrowserHostImpl> browserPtr;
CefRefPtr<CefFrame> framePtr;
int render_frame_id = -1;
@@ -1160,6 +1276,8 @@ std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
if (frame) {
render_frame_id = frame->GetRoutingID();
frame_tree_node_id = frame->GetFrameTreeNodeId();
// May return nullptr for requests originating from guest views.
browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame);
if (browserPtr) {
framePtr = browserPtr->GetFrameForHost(frame);
@@ -1167,14 +1285,15 @@ std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
}
}
// Flag subresource loads of custom schemes.
const bool is_external =
!is_navigation && !is_download && !request_initiator.scheme().empty() &&
!scheme::IsInternalHandledScheme(request_initiator.scheme());
auto init_state =
std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
init_state->Initialize(browser_context, browserPtr, framePtr,
render_process_id, render_frame_id, frame_tree_node_id,
is_navigation, is_download, request_initiator);
auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
wrapper->init_helper()->MaybeSetInitialized(std::move(init_state));
wrapper->Initialize(browser_context, browserPtr, framePtr, render_process_id,
render_frame_id, frame_tree_node_id, is_navigation,
is_download, request_initiator, is_external);
return wrapper;
}
@@ -1184,9 +1303,9 @@ std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
const network::ResourceRequest& request) {
CEF_REQUIRE_IOT();
auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
CEF_POST_TASK(CEF_UIT, base::BindOnce(
InitOnUIThread, base::Unretained(wrapper.get()),
web_contents_getter, frame_tree_node_id, request));
CEF_POST_TASK(CEF_UIT, base::BindOnce(InitOnUIThread, wrapper->init_helper(),
web_contents_getter, frame_tree_node_id,
request));
return wrapper;
}

View File

@@ -546,6 +546,21 @@ void CefRequestContextImpl::ClearCertificateExceptions(
this, callback));
}
void CefRequestContextImpl::ClearHttpAuthCredentials(
CefRefPtr<CefCompletionCallback> callback) {
if (net_service::IsEnabled()) {
GetBrowserContext(
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
base::Bind(&CefRequestContextImpl::ClearHttpAuthCredentialsInternal,
this, callback));
} else {
GetRequestContextImpl(
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
base::Bind(&CefRequestContextImpl::ClearHttpAuthCredentialsInternalOld,
this, callback));
}
}
void CefRequestContextImpl::CloseAllConnections(
CefRefPtr<CefCompletionCallback> callback) {
if (net_service::IsEnabled()) {
@@ -847,6 +862,36 @@ void CefRequestContextImpl::ClearCertificateExceptionsInternal(
}
}
void CefRequestContextImpl::ClearHttpAuthCredentialsInternal(
CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT();
browser_context->GetNetworkContext()->ClearHttpAuthCache(
base::Time(), base::Bind(&CefCompletionCallback::OnComplete, callback));
}
void CefRequestContextImpl::ClearHttpAuthCredentialsInternalOld(
CefRefPtr<CefCompletionCallback> callback,
scoped_refptr<CefURLRequestContextGetter> request_context) {
CEF_REQUIRE_IOT();
net::URLRequestContext* url_context = request_context->GetURLRequestContext();
if (url_context) {
net::HttpNetworkSession* http_session =
url_context->http_transaction_factory()->GetSession();
DCHECK(http_session);
http_session->http_auth_cache()->ClearEntriesAddedSince(base::Time());
http_session->CloseAllConnections();
}
if (callback) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefCompletionCallback::OnComplete, callback));
}
}
void CefRequestContextImpl::CloseAllConnectionsInternal(
CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context) {

View File

@@ -73,6 +73,8 @@ class CefRequestContextImpl : public CefRequestContext {
CefString& error) override;
void ClearCertificateExceptions(
CefRefPtr<CefCompletionCallback> callback) override;
void ClearHttpAuthCredentials(
CefRefPtr<CefCompletionCallback> callback) override;
void CloseAllConnections(CefRefPtr<CefCompletionCallback> callback) override;
void ResolveHost(const CefString& origin,
CefRefPtr<CefResolveCallback> callback) override;
@@ -157,6 +159,12 @@ class CefRequestContextImpl : public CefRequestContext {
void ClearCertificateExceptionsInternal(
CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context);
void ClearHttpAuthCredentialsInternal(
CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context);
void ClearHttpAuthCredentialsInternalOld(
CefRefPtr<CefCompletionCallback> callback,
scoped_refptr<CefURLRequestContextGetter> request_context);
void CloseAllConnectionsInternal(CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context);
void CloseAllConnectionsInternalOld(

View File

@@ -566,6 +566,13 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) {
}
}
if (features::kMimeHandlerViewInCrossProcessFrame.default_state ==
base::FEATURE_ENABLED_BY_DEFAULT) {
// TODO: Add support for cross-process mime handler view (see issue #2727)
disable_features.push_back(
features::kMimeHandlerViewInCrossProcessFrame.name);
}
if (!disable_features.empty()) {
DCHECK(!base::FeatureList::GetInstance());
std::string disable_features_str =
@@ -725,11 +732,9 @@ int CefMainDelegate::RunProcess(
bool CefMainDelegate::CreateUIThread(base::OnceClosure setup_callback) {
DCHECK(!ui_thread_);
std::unique_ptr<CefUIThread> thread;
thread.reset(new CefUIThread(std::move(setup_callback)));
thread->Start();
thread->WaitUntilThreadStarted();
ui_thread_.swap(thread);
ui_thread_.reset(new CefUIThread(std::move(setup_callback)));
ui_thread_->Start();
ui_thread_->WaitUntilThreadStarted();
InitMessagePumpFactoryForUI();
return true;

View File

@@ -1133,9 +1133,10 @@ void CefRequestImpl::Changed(uint8_t changes) {
}
if ((changes & kChangedHeaderMap) &&
!(backup_->backups_ & kChangedHeaderMap)) {
if (!backup_->headermap_)
backup_->headermap_.reset(new HeaderMap());
backup_->headermap_->swap(headermap_);
backup_->headermap_.reset(new HeaderMap());
if (!headermap_.empty()) {
backup_->headermap_->insert(headermap_.begin(), headermap_.end());
}
backup_->backups_ |= kChangedHeaderMap;
}
if ((changes & kChangedFlags) && !(backup_->backups_ & kChangedFlags)) {

View File

@@ -37,6 +37,7 @@
#include "libcef/renderer/render_message_filter.h"
#include "libcef/renderer/render_thread_observer.h"
#include "libcef/renderer/thread_util.h"
#include "libcef/renderer/url_loader_throttle_provider_impl.h"
#include "libcef/renderer/v8_impl.h"
#include "base/command_line.h"
@@ -603,12 +604,28 @@ void CefContentRendererClient::RunScriptsAtDocumentIdle(
}
void CefContentRendererClient::DevToolsAgentAttached() {
CEF_REQUIRE_RT();
// WebWorkers may be creating agents on a different thread.
if (!render_task_runner_->BelongsToCurrentThread()) {
render_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CefContentRendererClient::DevToolsAgentAttached,
base::Unretained(this)));
return;
}
++devtools_agent_count_;
}
void CefContentRendererClient::DevToolsAgentDetached() {
CEF_REQUIRE_RT();
// WebWorkers may be creating agents on a different thread.
if (!render_task_runner_->BelongsToCurrentThread()) {
render_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CefContentRendererClient::DevToolsAgentDetached,
base::Unretained(this)));
return;
}
--devtools_agent_count_;
if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) {
// When the last DevToolsAgent is detached the stack size is set to 0.
@@ -623,6 +640,12 @@ void CefContentRendererClient::CreateRendererService(
service_binding_.Bind(std::move(service_request));
}
std::unique_ptr<content::URLLoaderThrottleProvider>
CefContentRendererClient::CreateURLLoaderThrottleProvider(
content::URLLoaderThrottleProviderType provider_type) {
return std::make_unique<CefURLLoaderThrottleProviderImpl>(provider_type);
}
void CefContentRendererClient::OnBindInterface(
const service_manager::BindSourceInfo& remote_info,
const std::string& name,

View File

@@ -138,6 +138,9 @@ class CefContentRendererClient
void DevToolsAgentDetached() override;
void CreateRendererService(
service_manager::mojom::ServiceRequest service_request) override;
std::unique_ptr<content::URLLoaderThrottleProvider>
CreateURLLoaderThrottleProvider(
content::URLLoaderThrottleProviderType provider_type) override;
// service_manager::Service implementation.
void OnBindInterface(const service_manager::BindSourceInfo& remote_info,

View File

@@ -9,6 +9,7 @@
#include "libcef/renderer/blink_glue.h"
#include "base/logging.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "content/renderer/render_frame_impl.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -20,7 +21,7 @@ int64_t GetIdentifier(blink::WebLocalFrame* frame) {
// routing IDs are unique within a given renderer process.
content::RenderFrame* render_frame =
content::RenderFrame::FromWebFrame(frame);
return frame_util::MakeFrameId(render_frame->GetRenderView()->GetRoutingID(),
return frame_util::MakeFrameId(content::RenderThread::Get()->GetClientId(),
render_frame->GetRoutingID());
}

View File

@@ -0,0 +1,78 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libcef/renderer/url_loader_throttle_provider_impl.h"
#include "libcef/common/extensions/extensions_util.h"
#include <utility>
#include "base/feature_list.h"
#include "content/public/common/content_features.h"
#include "content/public/renderer/render_frame.h"
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/platform/web_url.h"
CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl(
content::URLLoaderThrottleProviderType type)
: type_(type) {
DETACH_FROM_THREAD(thread_checker_);
}
CefURLLoaderThrottleProviderImpl::~CefURLLoaderThrottleProviderImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl(
const CefURLLoaderThrottleProviderImpl& other)
: type_(other.type_) {
DETACH_FROM_THREAD(thread_checker_);
}
std::unique_ptr<content::URLLoaderThrottleProvider>
CefURLLoaderThrottleProviderImpl::Clone() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return base::WrapUnique(new CefURLLoaderThrottleProviderImpl(*this));
}
std::vector<std::unique_ptr<content::URLLoaderThrottle>>
CefURLLoaderThrottleProviderImpl::CreateThrottles(
int render_frame_id,
const blink::WebURLRequest& request,
content::ResourceType resource_type) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::vector<std::unique_ptr<content::URLLoaderThrottle>> throttles;
bool network_service_enabled =
base::FeatureList::IsEnabled(network::features::kNetworkService);
// Some throttles have already been added in the browser for frame resources.
// Don't add them for frame requests.
bool is_frame_resource = content::IsResourceTypeFrame(resource_type);
DCHECK(!is_frame_resource ||
type_ == content::URLLoaderThrottleProviderType::kFrame);
if (extensions::ExtensionsEnabled() && network_service_enabled &&
type_ == content::URLLoaderThrottleProviderType::kFrame &&
resource_type == content::ResourceType::kObject) {
content::RenderFrame* render_frame =
content::RenderFrame::FromRoutingID(render_frame_id);
auto mime_handlers =
extensions::MimeHandlerViewContainer::FromRenderFrame(render_frame);
GURL gurl(request.Url());
for (auto* handler : mime_handlers) {
auto throttle = handler->MaybeCreatePluginThrottle(gurl);
if (throttle) {
throttles.push_back(std::move(throttle));
break;
}
}
}
return throttles;
}
void CefURLLoaderThrottleProviderImpl::SetOnline(bool is_online) {}

View File

@@ -0,0 +1,45 @@
// Copyright 2018 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.
#ifndef CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
#define CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
#include <memory>
#include <vector>
#include "base/threading/thread_checker.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
// Instances must be constructed on the render thread, and then used and
// destructed on a single thread, which can be different from the render thread.
class CefURLLoaderThrottleProviderImpl
: public content::URLLoaderThrottleProvider {
public:
explicit CefURLLoaderThrottleProviderImpl(
content::URLLoaderThrottleProviderType type);
~CefURLLoaderThrottleProviderImpl() override;
// content::URLLoaderThrottleProvider implementation.
std::unique_ptr<content::URLLoaderThrottleProvider> Clone() override;
std::vector<std::unique_ptr<content::URLLoaderThrottle>> CreateThrottles(
int render_frame_id,
const blink::WebURLRequest& request,
content::ResourceType resource_type) override;
void SetOnline(bool is_online) override;
private:
// This copy constructor works in conjunction with Clone(), not intended for
// general use.
CefURLLoaderThrottleProviderImpl(
const CefURLLoaderThrottleProviderImpl& other);
content::URLLoaderThrottleProviderType type_;
THREAD_CHECKER(thread_checker_);
DISALLOW_ASSIGN(CefURLLoaderThrottleProviderImpl);
};
#endif // CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=29ac900a92c4ec966cc115aae96c49b545bc9db9$
// $hash=95cc8d1445764e1d1610b2047844b138e60542e6$
//
#include "libcef_dll/cpptoc/request_context_cpptoc.h"
@@ -373,6 +373,21 @@ void CEF_CALLBACK request_context_clear_certificate_exceptions(
CefCompletionCallbackCToCpp::Wrap(callback));
}
void CEF_CALLBACK request_context_clear_http_auth_credentials(
struct _cef_request_context_t* self,
cef_completion_callback_t* callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: callback
// Execute
CefRequestContextCppToC::Get(self)->ClearHttpAuthCredentials(
CefCompletionCallbackCToCpp::Wrap(callback));
}
void CEF_CALLBACK
request_context_close_all_connections(struct _cef_request_context_t* self,
cef_completion_callback_t* callback) {
@@ -549,6 +564,8 @@ CefRequestContextCppToC::CefRequestContextCppToC() {
GetStruct()->set_preference = request_context_set_preference;
GetStruct()->clear_certificate_exceptions =
request_context_clear_certificate_exceptions;
GetStruct()->clear_http_auth_credentials =
request_context_clear_http_auth_credentials;
GetStruct()->close_all_connections = request_context_close_all_connections;
GetStruct()->resolve_host = request_context_resolve_host;
GetStruct()->load_extension = request_context_load_extension;

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=370a54c21bec2aff5cf62b5897f5d43401e1ec31$
// $hash=ab373b720fe3c700867f86ad29ffc8b3e518a92c$
//
#include "libcef_dll/cpptoc/request_handler_cpptoc.h"
@@ -159,7 +159,7 @@ request_handler_get_resource_request_handler(
int CEF_CALLBACK
request_handler_get_auth_credentials(struct _cef_request_handler_t* self,
cef_browser_t* browser,
cef_frame_t* frame,
const cef_string_t* origin_url,
int isProxy,
const cef_string_t* host,
int port,
@@ -177,9 +177,9 @@ request_handler_get_auth_credentials(struct _cef_request_handler_t* self,
DCHECK(browser);
if (!browser)
return 0;
// Verify param: frame; type: refptr_diff
DCHECK(frame);
if (!frame)
// Verify param: origin_url; type: string_byref_const
DCHECK(origin_url);
if (!origin_url)
return 0;
// Verify param: host; type: string_byref_const
DCHECK(host);
@@ -193,7 +193,7 @@ request_handler_get_auth_credentials(struct _cef_request_handler_t* self,
// Execute
bool _retval = CefRequestHandlerCppToC::Get(self)->GetAuthCredentials(
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
CefBrowserCToCpp::Wrap(browser), CefString(origin_url),
isProxy ? true : false, CefString(host), port, CefString(realm),
CefString(scheme), CefAuthCallbackCToCpp::Wrap(callback));

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=8155639f093ff697fd30a9e330ae3470108251e5$
// $hash=5036c24365fa0fdb3d7efc54670f3123a7104fa0$
//
#include "libcef_dll/ctocpp/request_context_ctocpp.h"
@@ -355,6 +355,22 @@ void CefRequestContextCToCpp::ClearCertificateExceptions(
_struct, CefCompletionCallbackCppToC::Wrap(callback));
}
NO_SANITIZE("cfi-icall")
void CefRequestContextCToCpp::ClearHttpAuthCredentials(
CefRefPtr<CefCompletionCallback> callback) {
cef_request_context_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, clear_http_auth_credentials))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: callback
// Execute
_struct->clear_http_auth_credentials(
_struct, CefCompletionCallbackCppToC::Wrap(callback));
}
NO_SANITIZE("cfi-icall")
void CefRequestContextCToCpp::CloseAllConnections(
CefRefPtr<CefCompletionCallback> callback) {

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=00889895e17ac49f55668e395aa98a5f8312ee31$
// $hash=dd07d0157b7e9128b240ed2b059f2358ebf9fc09$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_CTOCPP_H_
@@ -63,6 +63,8 @@ class CefRequestContextCToCpp
CefString& error) OVERRIDE;
void ClearCertificateExceptions(
CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
void ClearHttpAuthCredentials(
CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
void CloseAllConnections(CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
void ResolveHost(const CefString& origin,
CefRefPtr<CefResolveCallback> callback) OVERRIDE;

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=f286ec7520ee6b589b3ecafa409eb3f71c081e27$
// $hash=ad2fb4fa8e7c8e265de6e03e2c8c8d3d28a7fd39$
//
#include "libcef_dll/ctocpp/request_handler_ctocpp.h"
@@ -151,7 +151,7 @@ CefRequestHandlerCToCpp::GetResourceRequestHandler(
NO_SANITIZE("cfi-icall")
bool CefRequestHandlerCToCpp::GetAuthCredentials(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& origin_url,
bool isProxy,
const CefString& host,
int port,
@@ -170,9 +170,9 @@ bool CefRequestHandlerCToCpp::GetAuthCredentials(
DCHECK(browser.get());
if (!browser.get())
return false;
// Verify param: frame; type: refptr_diff
DCHECK(frame.get());
if (!frame.get())
// Verify param: origin_url; type: string_byref_const
DCHECK(!origin_url.empty());
if (origin_url.empty())
return false;
// Verify param: host; type: string_byref_const
DCHECK(!host.empty());
@@ -186,8 +186,8 @@ bool CefRequestHandlerCToCpp::GetAuthCredentials(
// Execute
int _retval = _struct->get_auth_credentials(
_struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
isProxy, host.GetStruct(), port, realm.GetStruct(), scheme.GetStruct(),
_struct, CefBrowserCppToC::Wrap(browser), origin_url.GetStruct(), isProxy,
host.GetStruct(), port, realm.GetStruct(), scheme.GetStruct(),
CefAuthCallbackCppToC::Wrap(callback));
// Return type: bool

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=1e21398533e04c0dbd4143a3847b44fb43c64bc5$
// $hash=dab1901a0bbeda97ef1efc8e5852964c318775f6$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_HANDLER_CTOCPP_H_
@@ -54,7 +54,7 @@ class CefRequestHandlerCToCpp
const CefString& request_initiator,
bool& disable_default_handling) override;
bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& origin_url,
bool isProxy,
const CefString& host,
int port,

View File

@@ -368,9 +368,6 @@ patches = [
{
# macOS: Fix undesirable switch to discrete GPU during startup.
# https://bitbucket.org/chromiumembedded/cef/issues/2398
#
# macOS: Rely on symlinks to find the Libraries directory.
# https://bugs.chromium.org/p/chromium/issues/detail?id=757974#c23
'name': 'mac_gpu',
},
{
@@ -423,6 +420,14 @@ patches = [
# https://bitbucket.org/chromiumembedded/cef/issues/2622
'name': 'services_network_2622',
},
{
# Enhancements to NetworkService:
# - Support customization of request_id via SimpleURLLoader.
# - Remove the non-nullptr WebContents requirement from
# NetworkServiceClient::OnAuthRequired.
# https://bitbucket.org/chromiumembedded/cef/issues/2718
'name': 'services_network_request_id_2718',
},
{
# Windows: Remove the base::Value is_standard_layout assert which will fail
# for the cef_sandbox build, and which is no longer required.
@@ -445,10 +450,5 @@ patches = [
# unique_ptr types.
# https://chromium-review.googlesource.com/c/chromium/src/+/1584292
'name': 'compositor_frame_reporting_controller_1584292',
},
{
# Fix AssertContextWasntDestroyed due to pointer reuse.
# https://chromium-review.googlesource.com/c/chromium/src/+/1590418
'name': 'simple_dependency_manager_1590418',
}
]

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
index 987b36217aad..832eab3ee56a 100644
index 600fe26a3f35..1888bc494bcc 100644
--- chrome/browser/BUILD.gn
+++ chrome/browser/BUILD.gn
@@ -8,6 +8,7 @@ import("//build/config/features.gni")
@@ -29,7 +29,7 @@ index 987b36217aad..832eab3ee56a 100644
if (is_android) {
sources += [
"after_startup_task_utils_android.cc",
@@ -3916,7 +3922,7 @@ jumbo_split_static_library("browser") {
@@ -3917,7 +3923,7 @@ jumbo_split_static_library("browser") {
]
}

View File

@@ -51,7 +51,7 @@ index 6c8e21f6f5fe..4496c5579265 100644
override;
network::NetworkQualityTracker* network_quality_tracker() override;
diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
index 535c4f04c0f3..8cd8768022ae 100644
index 7561cab16804..407f7a6008a3 100644
--- chrome/browser/ui/BUILD.gn
+++ chrome/browser/ui/BUILD.gn
@@ -9,6 +9,7 @@ import("//build/config/features.gni")

View File

@@ -1,8 +1,8 @@
diff --git chrome/browser/chrome_content_browser_client.cc chrome/browser/chrome_content_browser_client.cc
index cf4250c7ba26..b8a05db7cced 100644
index 26c3593d94d0..1ca67c62e464 100644
--- chrome/browser/chrome_content_browser_client.cc
+++ chrome/browser/chrome_content_browser_client.cc
@@ -1049,12 +1049,16 @@ void LaunchURL(
@@ -1063,12 +1063,16 @@ void LaunchURL(
}
}
@@ -22,7 +22,7 @@ index cf4250c7ba26..b8a05db7cced 100644
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUserAgent)) {
diff --git chrome/browser/chrome_content_browser_client.h chrome/browser/chrome_content_browser_client.h
index 07e0e051ff1d..41337a1719a1 100644
index 6bbed7653db9..f663648004ee 100644
--- chrome/browser/chrome_content_browser_client.h
+++ chrome/browser/chrome_content_browser_client.h
@@ -77,7 +77,8 @@ class Origin;

View File

@@ -125,7 +125,7 @@ index daf826ece047..615200c4b41c 100644
// If we broke out of the loop, we have found an enabled plugin.
bool enabled = i < matching_plugins.size();
diff --git chrome/browser/plugins/plugin_utils.cc chrome/browser/plugins/plugin_utils.cc
index 01ea0ba7f0cb..2828896bbcad 100644
index 01ea0ba7f0cb..f573503df5c4 100644
--- chrome/browser/plugins/plugin_utils.cc
+++ chrome/browser/plugins/plugin_utils.cc
@@ -5,6 +5,7 @@
@@ -148,12 +148,15 @@ index 01ea0ba7f0cb..2828896bbcad 100644
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/info_map.h"
#include "extensions/common/constants.h"
@@ -180,10 +186,23 @@ PluginUtils::GetMimeTypeToExtensionIdMap(
@@ -180,10 +186,26 @@ PluginUtils::GetMimeTypeToExtensionIdMap(
content::ResourceContext* resource_context) {
base::flat_map<std::string, std::string> mime_type_to_extension_id_map;
#if BUILDFLAG(ENABLE_EXTENSIONS)
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (!extensions::ExtensionsEnabled())
+ return mime_type_to_extension_id_map;
+
+ CefResourceContext* context =
+ static_cast<CefResourceContext*>(resource_context);
+ bool profile_is_off_the_record = context->IsOffTheRecord();
@@ -172,7 +175,7 @@ index 01ea0ba7f0cb..2828896bbcad 100644
std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
// Go through the white-listed extensions and try to use them to intercept
// the URL request.
@@ -198,7 +217,7 @@ PluginUtils::GetMimeTypeToExtensionIdMap(
@@ -198,7 +220,7 @@ PluginUtils::GetMimeTypeToExtensionIdMap(
}
if (extension_id == extension_misc::kPdfExtensionId &&

View File

@@ -262,10 +262,10 @@ index 3009401dac6b..b4c5a9e2db50 100644
};
diff --git content/common/frame_messages.h content/common/frame_messages.h
index 8673d65844ea..7d13c72dca9b 100644
index 91e10a619343..9eeb813ea6d7 100644
--- content/common/frame_messages.h
+++ content/common/frame_messages.h
@@ -1286,9 +1286,10 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_PepperStopsPlayback,
@@ -1289,9 +1289,10 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_PepperStopsPlayback,
// type. If there is no matching plugin, |found| is false.
// |actual_mime_type| is the actual mime type supported by the
// found plugin.
@@ -278,10 +278,10 @@ index 8673d65844ea..7d13c72dca9b 100644
std::string /* mime_type */,
bool /* found */,
diff --git content/public/browser/content_browser_client.h content/public/browser/content_browser_client.h
index 0a1bf5d0b4d1..6dea4f0f4a44 100644
index 39174b67d1d3..f5a825c113cf 100644
--- content/public/browser/content_browser_client.h
+++ content/public/browser/content_browser_client.h
@@ -1460,6 +1460,15 @@ class CONTENT_EXPORT ContentBrowserClient {
@@ -1466,6 +1466,15 @@ class CONTENT_EXPORT ContentBrowserClient {
network::mojom::URLLoaderFactoryRequest* factory_request,
network::mojom::URLLoaderFactory*& out_factory);
@@ -297,7 +297,7 @@ index 0a1bf5d0b4d1..6dea4f0f4a44 100644
// Creates an OverlayWindow to be used for Picture-in-Picture. This window
// will house the content shown when in Picture-in-Picture mode. This will
// return a new OverlayWindow.
@@ -1527,6 +1536,10 @@ class CONTENT_EXPORT ContentBrowserClient {
@@ -1533,6 +1542,10 @@ class CONTENT_EXPORT ContentBrowserClient {
// Used as part of the user agent string.
virtual std::string GetProduct() const;
@@ -372,10 +372,10 @@ index 8935697155f5..179b6ebf1360 100644
virtual void FocusedNodeChanged(const blink::WebNode& node) {}
diff --git content/renderer/render_frame_impl.cc content/renderer/render_frame_impl.cc
index c75b6177f066..860bbe9e1c14 100644
index dc3c7420d89d..7cf57b285d24 100644
--- content/renderer/render_frame_impl.cc
+++ content/renderer/render_frame_impl.cc
@@ -3996,7 +3996,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
@@ -4047,7 +4047,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
std::string mime_type;
bool found = false;
Send(new FrameHostMsg_GetPluginInfo(
@@ -385,7 +385,7 @@ index c75b6177f066..860bbe9e1c14 100644
params.mime_type.Utf8(), &found, &info, &mime_type));
if (!found)
return nullptr;
@@ -4422,6 +4423,8 @@ void RenderFrameImpl::FrameDetached(DetachType type) {
@@ -4473,6 +4474,8 @@ void RenderFrameImpl::FrameDetached(DetachType type) {
void RenderFrameImpl::FrameFocused() {
Send(new FrameHostMsg_FrameFocused(routing_id_));

View File

@@ -68,10 +68,10 @@ index c3511e3e6a66..3500f4a2b005 100644
void ChromeBrowserMainExtraPartsViewsLinux::ToolkitInitialized() {
diff --git chrome/test/BUILD.gn chrome/test/BUILD.gn
index 5406779a17c2..b1ed0f2c970b 100644
index 63be9ca9369f..9f73a3c841f3 100644
--- chrome/test/BUILD.gn
+++ chrome/test/BUILD.gn
@@ -4159,7 +4159,7 @@ test("unit_tests") {
@@ -4170,7 +4170,7 @@ test("unit_tests") {
"../browser/ui/input_method/input_method_engine_unittest.cc",
]
}
@@ -80,7 +80,7 @@ index 5406779a17c2..b1ed0f2c970b 100644
sources +=
[ "../browser/ui/libgtkui/select_file_dialog_impl_gtk_unittest.cc" ]
deps += [ "//build/config/linux/gtk" ]
@@ -4180,7 +4180,7 @@ test("unit_tests") {
@@ -4191,7 +4191,7 @@ test("unit_tests") {
if (use_gio) {
configs += [ "//build/linux:gio_config" ]
}
@@ -89,7 +89,7 @@ index 5406779a17c2..b1ed0f2c970b 100644
deps += [ "//chrome/browser/ui/libgtkui" ]
}
@@ -5206,7 +5206,7 @@ if (!is_android) {
@@ -5217,7 +5217,7 @@ if (!is_android) {
# suites, it seems like one or another starts timing out too.
"../browser/ui/views/keyboard_access_browsertest.cc",
]

View File

@@ -1,5 +1,5 @@
diff --git base/files/file_path_watcher_linux.cc base/files/file_path_watcher_linux.cc
index 22732f2864ef..7d5caef5c3b0 100644
index 3f5eb8e2e002..245a0ca9055f 100644
--- base/files/file_path_watcher_linux.cc
+++ base/files/file_path_watcher_linux.cc
@@ -5,6 +5,7 @@
@@ -15,10 +15,10 @@ index 22732f2864ef..7d5caef5c3b0 100644
#include <algorithm>
+#include <array>
#include <fstream>
#include <map>
#include <memory>
#include <set>
@@ -220,22 +222,15 @@ void InotifyReaderThreadDelegate::ThreadMain() {
@@ -263,22 +265,15 @@ void InotifyReaderThreadDelegate::ThreadMain() {
PlatformThread::SetName("inotify_reader");
// Make sure the file descriptors are good for use with select().

View File

@@ -1,5 +1,5 @@
diff --git ui/gl/init/gl_initializer_mac.cc ui/gl/init/gl_initializer_mac.cc
index 85cab0eaef3e..37b2d42a34f5 100644
index 8d690474060f..03059842b1a4 100644
--- ui/gl/init/gl_initializer_mac.cc
+++ ui/gl/init/gl_initializer_mac.cc
@@ -46,11 +46,8 @@ bool InitializeOneOffForSandbox() {
@@ -16,14 +16,3 @@ index 85cab0eaef3e..37b2d42a34f5 100644
if (GetGLImplementation() == kGLImplementationAppleGL) {
attribs.push_back(kCGLPFARendererID);
attribs.push_back(
@@ -102,8 +99,8 @@ bool InitializeStaticEGLInternal(GLImplementation implementation) {
// as app bundles. In that case, the .dylib is next to the executable.
base::FilePath base_dir;
if (base::mac::AmIBundled()) {
- base_dir =
- base::mac::FrameworkBundlePath().Append("Versions/Current/Libraries/");
+ // Rely on symlinks to find the correct version.
+ base_dir = base::mac::FrameworkBundlePath().Append("Libraries/");
} else {
if (!base::PathService::Get(base::FILE_EXE, &base_dir)) {
LOG(ERROR) << "PathService::Get failed.";

View File

@@ -1,5 +1,5 @@
diff --git content/public/common/common_param_traits_macros.h content/public/common/common_param_traits_macros.h
index 24bded9417c5..cb5d04ab32ab 100644
index c97b4e009baa..04dee2983825 100644
--- content/public/common/common_param_traits_macros.h
+++ content/public/common/common_param_traits_macros.h
@@ -189,6 +189,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
@@ -35,7 +35,7 @@ index a83015f3629a..fe79480e9af7 100644
bool record_whole_document;
diff --git content/renderer/render_view_impl.cc content/renderer/render_view_impl.cc
index 3e328daa5827..7d0869aa29fd 100644
index 83e40b6568da..b47165e7ac74 100644
--- content/renderer/render_view_impl.cc
+++ content/renderer/render_view_impl.cc
@@ -1026,6 +1026,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/renderer_preferences_util.cc chrome/browser/renderer_preferences_util.cc
index f5ed7f0683c5..5b31fb309985 100644
index 77a1a97f5e8e..c4f1c94db8b3 100644
--- chrome/browser/renderer_preferences_util.cc
+++ chrome/browser/renderer_preferences_util.cc
@@ -29,7 +29,8 @@

View File

@@ -35,7 +35,7 @@ index 2b24d1ac1b5b..6577495d87a9 100644
base_cache_path.Append(chrome::kCacheDirname);
network_context_params->http_cache_max_size =
diff --git chrome/browser/profiles/profile.h chrome/browser/profiles/profile.h
index e77d8abd6601..88331e9af5e0 100644
index 737f5f8b8193..241edaa39671 100644
--- chrome/browser/profiles/profile.h
+++ chrome/browser/profiles/profile.h
@@ -321,6 +321,11 @@ class Profile : public content::BrowserContext {
@@ -132,10 +132,10 @@ index 8be1b9dea5f7..30f23449ac51 100644
void CookieManager::SetForceKeepSessionState() {
diff --git services/network/network_context.cc services/network/network_context.cc
index 9d6f7b930e11..c16e5ca90c14 100644
index 9349b0bea419..167b6df982d0 100644
--- services/network/network_context.cc
+++ services/network/network_context.cc
@@ -1742,6 +1742,7 @@ URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder(
@@ -1753,6 +1753,7 @@ URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder(
}
scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store;
@@ -143,7 +143,7 @@ index 9d6f7b930e11..c16e5ca90c14 100644
if (params_->cookie_path) {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
base::MessageLoopCurrent::Get()->task_runner();
@@ -1769,18 +1770,27 @@ URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder(
@@ -1780,18 +1781,27 @@ URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder(
session_cleanup_cookie_store =
base::MakeRefCounted<SessionCleanupCookieStore>(sqlite_store);

View File

@@ -0,0 +1,84 @@
diff --git content/browser/network_service_client.cc content/browser/network_service_client.cc
index 8978b4628ffe..f4f554c940b5 100644
--- content/browser/network_service_client.cc
+++ content/browser/network_service_client.cc
@@ -239,10 +239,6 @@ class LoginHandlerDelegate {
}
WebContents* web_contents = web_contents_getter_.Run();
- if (!web_contents) {
- OnAuthCredentials(base::nullopt);
- return;
- }
// WeakPtr is not strictly necessary here due to OnRequestCancelled.
creating_login_delegate_ = true;
@@ -439,11 +435,6 @@ void NetworkServiceClient::OnAuthRequired(
base::Callback<WebContents*(void)> web_contents_getter =
base::BindRepeating(GetWebContents, process_id, routing_id);
- if (!web_contents_getter.Run()) {
- std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt);
- return;
- }
-
if (ResourceDispatcherHostImpl::Get()->DoNotPromptForLogin(
static_cast<ResourceType>(resource_type), url, site_for_cookies)) {
std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt);
diff --git services/network/public/cpp/simple_url_loader.cc services/network/public/cpp/simple_url_loader.cc
index 0c4101672018..75c051f2bc44 100644
--- services/network/public/cpp/simple_url_loader.cc
+++ services/network/public/cpp/simple_url_loader.cc
@@ -227,6 +227,7 @@ class SimpleURLLoaderImpl : public SimpleURLLoader,
uint64_t length = std::numeric_limits<uint64_t>::max()) override;
void SetRetryOptions(int max_retries, int retry_mode) override;
void SetTimeoutDuration(base::TimeDelta timeout_duration) override;
+ void SetRequestId(int32_t request_id) override;
int NetError() const override;
const ResourceResponseHead* ResponseInfo() const override;
@@ -344,6 +345,8 @@ class SimpleURLLoaderImpl : public SimpleURLLoader,
// The next values contain all the information required to restart the
// request.
+ int32_t request_id_ = 0;
+
// Populated in the constructor, and cleared once no longer needed, when no
// more retries are possible.
std::unique_ptr<ResourceRequest> resource_request_;
@@ -1368,6 +1371,12 @@ void SimpleURLLoaderImpl::SetTimeoutDuration(base::TimeDelta timeout_duration) {
timeout_duration_ = timeout_duration;
}
+void SimpleURLLoaderImpl::SetRequestId(int32_t request_id) {
+ // Check if a request has not yet been started.
+ DCHECK(!body_handler_);
+ request_id_ = request_id;
+}
+
int SimpleURLLoaderImpl::NetError() const {
// Should only be called once the request is compelete.
DCHECK(request_state_->finished);
@@ -1516,7 +1525,7 @@ void SimpleURLLoaderImpl::StartRequest(
string_upload_data_pipe_getter_->GetPtrForNewUpload());
}
url_loader_factory->CreateLoaderAndStart(
- mojo::MakeRequest(&url_loader_), 0 /* routing_id */, 0 /* request_id */,
+ mojo::MakeRequest(&url_loader_), 0 /* routing_id */, request_id_,
0 /* options */, *resource_request_, std::move(client_ptr),
net::MutableNetworkTrafficAnnotationTag(annotation_tag_));
diff --git services/network/public/cpp/simple_url_loader.h services/network/public/cpp/simple_url_loader.h
index f81788d25fda..ba8948be5ebf 100644
--- services/network/public/cpp/simple_url_loader.h
+++ services/network/public/cpp/simple_url_loader.h
@@ -324,6 +324,9 @@ class COMPONENT_EXPORT(NETWORK_CPP) SimpleURLLoader {
// as much time as it wants.
virtual void SetTimeoutDuration(base::TimeDelta timeout_duration) = 0;
+ // Set the ID that will be associated with the request.
+ virtual void SetRequestId(int32_t request_id) = 0;
+
// Returns the net::Error representing the final status of the request. May
// only be called once the loader has informed the caller of completion.
virtual int NetError() const = 0;

View File

@@ -1,49 +0,0 @@
diff --git chrome/browser/profiles/profile_key.cc chrome/browser/profiles/profile_key.cc
index b225f2b..946403e 100644
--- chrome/browser/profiles/profile_key.cc
+++ chrome/browser/profiles/profile_key.cc
@@ -5,9 +5,12 @@
#include "chrome/browser/profiles/profile_key.h"
#include "base/logging.h"
+#include "components/keyed_service/core/simple_dependency_manager.h"
ProfileKey::ProfileKey(const base::FilePath& path, ProfileKey* original_key)
- : SimpleFactoryKey(path), prefs_(nullptr), original_key_(original_key) {}
+ : SimpleFactoryKey(path), prefs_(nullptr), original_key_(original_key) {
+ SimpleDependencyManager::GetInstance()->MarkContextLive(this);
+}
ProfileKey::~ProfileKey() = default;
diff --git components/keyed_service/core/simple_dependency_manager.cc components/keyed_service/core/simple_dependency_manager.cc
index 254c6ef..57d20b9 100644
--- components/keyed_service/core/simple_dependency_manager.cc
+++ components/keyed_service/core/simple_dependency_manager.cc
@@ -43,6 +43,10 @@
DependencyManager::CreateContextServices(key, true);
}
+void SimpleDependencyManager::MarkContextLive(SimpleFactoryKey* key) {
+ DependencyManager::MarkContextLive(key);
+}
+
SimpleDependencyManager::SimpleDependencyManager() = default;
SimpleDependencyManager::~SimpleDependencyManager() = default;
diff --git components/keyed_service/core/simple_dependency_manager.h components/keyed_service/core/simple_dependency_manager.h
index 72fa74c..480f971 100644
--- components/keyed_service/core/simple_dependency_manager.h
+++ components/keyed_service/core/simple_dependency_manager.h
@@ -35,6 +35,11 @@
// ServiceIsNULLWhileTesting().
void CreateServicesForTest(SimpleFactoryKey* key);
+ // Marks |context| as live (i.e., not stale). This method can be called as a
+ // safeguard against |AssertContextWasntDestroyed()| checks going off due to
+ // |context| aliasing an instance from a prior construction.
+ void MarkContextLive(SimpleFactoryKey* key);
+
private:
~SimpleDependencyManager() override;

View File

@@ -52,7 +52,7 @@ index b2b3920da3b0..686afc464b42 100644
std::move(stats_db), BrowserFeatureProvider::GetFactoryCB());
decode_history = new_decode_history.get();
diff --git content/browser/renderer_host/render_process_host_impl.cc content/browser/renderer_host/render_process_host_impl.cc
index f3a90e61f2b4..a9d322d66d86 100644
index 0866af8555cd..cc5750725c30 100644
--- content/browser/renderer_host/render_process_host_impl.cc
+++ content/browser/renderer_host/render_process_host_impl.cc
@@ -2203,6 +2203,9 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {

View File

@@ -39,7 +39,7 @@ index cce16a111356..9f0a8b73adb5 100644
virtual void MenuWillShow() {}
diff --git ui/gfx/render_text.cc ui/gfx/render_text.cc
index 9c38cd6d4fdb..dcd34308a8bc 100644
index 9d665b99613c..543f79f3beb7 100644
--- ui/gfx/render_text.cc
+++ ui/gfx/render_text.cc
@@ -514,6 +514,14 @@ void RenderText::SetElideBehavior(ElideBehavior elide_behavior) {
@@ -240,7 +240,7 @@ index 9df5c850d12d..e7007ffbb762 100644
std::unique_ptr<SelectionController> selection_controller_;
diff --git ui/views/controls/menu/menu_controller.cc ui/views/controls/menu/menu_controller.cc
index 5e630a1a5f47..a3725641c2db 100644
index eb93ba807319..b558892cc737 100644
--- ui/views/controls/menu/menu_controller.cc
+++ ui/views/controls/menu/menu_controller.cc
@@ -2570,8 +2570,13 @@ MenuItemView* MenuController::FindNextSelectableMenuItem(

View File

@@ -411,7 +411,7 @@ index 5bcb8d8b9bae..020fa85573aa 100644
if (native_widget_delegate->IsDialogBox()) {
*style |= DS_MODALFRAME;
diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc
index fb8e820175ac..66c5cb91f7e8 100644
index 443003518ef8..c43981fbda23 100644
--- ui/views/win/hwnd_message_handler.cc
+++ ui/views/win/hwnd_message_handler.cc
@@ -2918,10 +2918,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,

View File

@@ -1,8 +1,8 @@
diff --git content/browser/web_contents/web_contents_impl.cc content/browser/web_contents/web_contents_impl.cc
index 1491bf580c59..ab2c83357303 100644
index 466510566050..edb615bb11b4 100644
--- content/browser/web_contents/web_contents_impl.cc
+++ content/browser/web_contents/web_contents_impl.cc
@@ -2068,21 +2068,30 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
@@ -2070,21 +2070,30 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
std::string unique_name;
frame_tree_.root()->SetFrameName(params.main_frame_name, unique_name);
@@ -45,7 +45,7 @@ index 1491bf580c59..ab2c83357303 100644
CHECK(render_view_host_delegate_view_);
CHECK(view_.get());
@@ -2781,6 +2790,15 @@ void WebContentsImpl::CreateNewWindow(
@@ -2783,6 +2792,15 @@ void WebContentsImpl::CreateNewWindow(
create_params.renderer_initiated_creation =
main_frame_route_id != MSG_ROUTING_NONE;
@@ -61,7 +61,7 @@ index 1491bf580c59..ab2c83357303 100644
std::unique_ptr<WebContents> new_contents;
if (!is_guest) {
create_params.context = view_->GetNativeView();
@@ -2813,7 +2831,7 @@ void WebContentsImpl::CreateNewWindow(
@@ -2815,7 +2833,7 @@ void WebContentsImpl::CreateNewWindow(
// TODO(brettw): It seems bogus that we have to call this function on the
// newly created object and give it one of its own member variables.
new_view->CreateViewForWidget(
@@ -70,7 +70,7 @@ index 1491bf580c59..ab2c83357303 100644
}
// Save the created window associated with the route so we can show it
// later.
@@ -6372,7 +6390,7 @@ InterstitialPageImpl* WebContentsImpl::GetInterstitialForRenderManager() {
@@ -6382,7 +6400,7 @@ InterstitialPageImpl* WebContentsImpl::GetInterstitialForRenderManager() {
void WebContentsImpl::CreateRenderWidgetHostViewForRenderManager(
RenderViewHost* render_view_host) {
RenderWidgetHostViewBase* rwh_view =

View File

@@ -44,7 +44,7 @@ index a616fafed51f..dae131dad5de 100644
.Top()
.GetSecurityContext()
diff --git third_party/blink/renderer/core/frame/local_frame.cc third_party/blink/renderer/core/frame/local_frame.cc
index dd0e2f0df7b5..3c3ff59f72a9 100644
index c1f7d53655bd..728fec52942f 100644
--- third_party/blink/renderer/core/frame/local_frame.cc
+++ third_party/blink/renderer/core/frame/local_frame.cc
@@ -1257,7 +1257,7 @@ FrameResourceCoordinator* LocalFrame::GetFrameResourceCoordinator() {
@@ -85,10 +85,10 @@ index 6435384652b7..79bd103df30d 100644
void DevToolsSession::FlushProtocolNotifications() {
diff --git third_party/blink/renderer/core/page/page.cc third_party/blink/renderer/core/page/page.cc
index 5480f0e29789..3bf2f35c9741 100644
index 6cc6c5a6f38c..314334cde0d8 100644
--- third_party/blink/renderer/core/page/page.cc
+++ third_party/blink/renderer/core/page/page.cc
@@ -180,7 +180,8 @@ Page::Page(PageClients& page_clients)
@@ -185,7 +185,8 @@ Page::Page(PageClients& page_clients)
MakeGarbageCollected<OverscrollController>(GetVisualViewport(),
GetChromeClient())),
link_highlights_(MakeGarbageCollected<LinkHighlights>(*this)),
@@ -98,7 +98,7 @@ index 5480f0e29789..3bf2f35c9741 100644
// TODO(pdr): Initialize |validation_message_client_| lazily.
validation_message_client_(
MakeGarbageCollected<ValidationMessageClientImpl>(*this)),
@@ -337,21 +338,40 @@ void Page::InitialStyleChanged() {
@@ -344,21 +345,40 @@ void Page::InitialStyleChanged() {
}
}
@@ -148,7 +148,7 @@ index 5480f0e29789..3bf2f35c9741 100644
page->NotifyPluginsChanged();
}
}
@@ -786,7 +806,8 @@ void Page::Trace(blink::Visitor* visitor) {
@@ -801,7 +821,8 @@ void Page::Trace(blink::Visitor* visitor) {
visitor->Trace(link_highlights_);
visitor->Trace(spatial_navigation_controller_);
visitor->Trace(main_frame_);
@@ -159,7 +159,7 @@ index 5480f0e29789..3bf2f35c9741 100644
visitor->Trace(plugins_changed_observers_);
visitor->Trace(next_related_page_);
diff --git third_party/blink/renderer/core/page/page.h third_party/blink/renderer/core/page/page.h
index f3d748e4a3e7..3750ba015d76 100644
index eb5e930c4653..3a12676266d3 100644
--- third_party/blink/renderer/core/page/page.h
+++ third_party/blink/renderer/core/page/page.h
@@ -140,7 +140,8 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
@@ -172,7 +172,7 @@ index f3d748e4a3e7..3750ba015d76 100644
// Resets the plugin data for all pages in the renderer process and notifies
// PluginsChangedObservers.
@@ -364,7 +365,8 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
@@ -366,7 +367,8 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
const Member<LinkHighlights> link_highlights_;
Member<SpatialNavigationController> spatial_navigation_controller_;

View File

@@ -1,8 +1,8 @@
diff --git third_party/blink/renderer/core/input/pointer_event_manager.cc third_party/blink/renderer/core/input/pointer_event_manager.cc
index b84e3bdd6679..a0d65d9a65a1 100644
index 6a7744b5f75f..1368809f0740 100644
--- third_party/blink/renderer/core/input/pointer_event_manager.cc
+++ third_party/blink/renderer/core/input/pointer_event_manager.cc
@@ -285,7 +285,7 @@ void PointerEventManager::HandlePointerInterruption(
@@ -311,7 +311,7 @@ void PointerEventManager::HandlePointerInterruption(
for (auto pointer_event : canceled_pointer_events) {
// If we are sending a pointercancel we have sent the pointerevent to some
// target before.

View File

@@ -11,7 +11,7 @@ index f831c084e1d3..80dd4ea3a154 100644
// Cancels and hides the current popup (datetime, select...) if any.
virtual void CancelPagePopup() = 0;
diff --git third_party/blink/renderer/core/exported/web_view_impl.cc third_party/blink/renderer/core/exported/web_view_impl.cc
index fa2150289b4f..611dffb1ef7d 100644
index 41e11e56e95b..e854d0326c2c 100644
--- third_party/blink/renderer/core/exported/web_view_impl.cc
+++ third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -238,8 +238,13 @@ void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) {
@@ -39,7 +39,7 @@ index fa2150289b4f..611dffb1ef7d 100644
fullscreen_controller_(std::make_unique<FullscreenController>(this)) {
if (!AsView().client) {
diff --git third_party/blink/renderer/core/exported/web_view_impl.h third_party/blink/renderer/core/exported/web_view_impl.h
index aaa17462ee65..647b51d8fddc 100644
index 64a22db62dba..09713163f4a0 100644
--- third_party/blink/renderer/core/exported/web_view_impl.h
+++ third_party/blink/renderer/core/exported/web_view_impl.h
@@ -105,7 +105,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,

View File

@@ -1,8 +1,8 @@
diff --git chrome/app/generated_resources.grd chrome/app/generated_resources.grd
index 4989fa559ee6..c6859944e8b4 100644
index 27c735629140..929ddbca4a6c 100644
--- chrome/app/generated_resources.grd
+++ chrome/app/generated_resources.grd
@@ -4644,7 +4644,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
@@ -4645,7 +4645,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
</message>
</if>
<message name="IDS_PLUGIN_BLOCKED_BY_POLICY" desc="The placeholder text for a plugin blocked by enterprise policy.">

View File

@@ -702,6 +702,32 @@ CefRefPtr<CefResourceRequestHandler> ClientHandler::GetResourceRequestHandler(
return this;
}
bool ClientHandler::GetAuthCredentials(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
bool isProxy,
const CefString& host,
int port,
const CefString& realm,
const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) {
CEF_REQUIRE_IO_THREAD();
// Used for testing authentication with a proxy server.
// For example, CCProxy on Windows.
if (isProxy) {
callback->Continue("guest", "guest");
return true;
}
// Used for testing authentication with https://jigsaw.w3.org/HTTP/.
if (host == "jigsaw.w3.org") {
callback->Continue("guest", "guest");
return true;
}
return false;
}
bool ClientHandler::OnQuotaRequest(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
int64 new_size,

View File

@@ -229,6 +229,14 @@ class ClientHandler : public CefClient,
bool is_download,
const CefString& request_initiator,
bool& disable_default_handling) OVERRIDE;
bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
bool isProxy,
const CefString& host,
int port,
const CefString& realm,
const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) OVERRIDE;
bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
int64 new_size,

View File

@@ -126,9 +126,10 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
const RequestClient::Callback& request_callback =
base::Bind(&Handler::OnRequestComplete, base::Unretained(this));
// Create and start the new CefURLRequest.
urlrequest_ = CefURLRequest::Create(
cef_request, new RequestClient(request_callback), NULL);
// Create and start a new CefURLRequest associated with the frame, so
// that it shares authentication with ClientHandler::GetAuthCredentials.
urlrequest_ = frame->CreateURLRequest(
cef_request, new RequestClient(request_callback));
return true;
}

View File

@@ -7,11 +7,13 @@
<ul>
<li><a href="http://mudcu.be/labs/JS1k/BreathingGalaxies.html">Accelerated 2D Canvas</a></li>
<li><a href="http://webkit.org/blog-files/3d-transforms/poster-circle.html">Accelerated Layers</a></li>
<li><a href="https://jigsaw.w3.org/HTTP/Basic/">Authentication (Basic)</a> - credentials returned via GetAuthCredentials</li>
<li><a href="https://jigsaw.w3.org/HTTP/Digest/">Authentication (Digest)</a> - credentials returned via GetAuthCredentials</li>
<li><a href="http://html5advent2011.digitpaint.nl/3/index.html">Cursors</a></li>
<li><a href="dialogs">Dialogs</a></li>
<li><a href="http://html5demos.com/drag">Drag & Drop</a></li>
<li><a href="draggable">Draggable Regions</a></li>
<li><a href="drm">DRM (Clearkey, Widevine)</a></li>
<li><a href="drm">DRM (Clearkey, Widevine)</a> - Widevine requires setup as described in cef_web_plugin.h</li>
<li><a href="http://www.adobe.com/software/flash/about/">Flash Plugin</a> - requires "enable-system-flash" flag on Win/Mac and "ppapi-flash-path", "ppapi-flash-version" flags on Linux</li>
<li><a href="http://www.html5test.com">HTML5 Feature Test</a></li>
<li><a href="http://html5-demos.appspot.com/static/filesystem/filer.js/demos/index.html">HTML5 Filesystem</a> - requires "cache-path" flag</li>
@@ -36,7 +38,7 @@
<li><a href="urlrequest">CefURLRequest</a></li>
<li><a href="xmlhttprequest">XMLHttpRequest</a></li>
<li><a href="javascript:window.print();">Print this page with &quot;javascript:window.print();&quot;</a></li>
<li><a href="https://patrickhlauke.github.io/touch">Touch Feature Tests</a> - requires "touch-events=enabled" flag (and CAPS LOCK on Mac for Trackpad simulation) </li>
<li><a href="https://patrickhlauke.github.io/touch">Touch Feature Tests</a> - requires "touch-events=enabled" flag (and CAPS LOCK on Mac for Trackpad simulation)</li>
</ul>
</body>
</html>

View File

@@ -1067,13 +1067,13 @@ std::string GetCookieAccessUrl2(const std::string& scheme,
}
void TestCookieString(const std::string& cookie_str,
TrackCallback& got_cookie_js,
TrackCallback& got_cookie_net) {
int& cookie_js_ct,
int& cookie_net_ct) {
if (cookie_str.find("name_js=value_js") != std::string::npos) {
got_cookie_js.yes();
cookie_js_ct++;
}
if (cookie_str.find("name_net=value_net") != std::string::npos) {
got_cookie_net.yes();
cookie_net_ct++;
}
}
@@ -1081,9 +1081,9 @@ struct CookieAccessData {
CefRefPtr<CefResponse> response;
std::string response_data;
TrackCallback got_request_;
TrackCallback got_cookie_js_;
TrackCallback got_cookie_net_;
int request_ct_ = 0;
int cookie_js_ct_ = 0;
int cookie_net_ct_ = 0;
};
class CookieAccessResponseHandler {
@@ -1116,7 +1116,7 @@ class CookieAccessSchemeHandler : public CefResourceHandler {
CefRequest::HeaderMap headerMap;
request->GetHeaderMap(headerMap);
const std::string& cookie_str = GetHeaderValue(headerMap, "Cookie");
TestCookieString(cookie_str, data_->got_cookie_js_, data_->got_cookie_net_);
TestCookieString(cookie_str, data_->cookie_js_ct_, data_->cookie_net_ct_);
// Continue immediately.
callback->Continue();
@@ -1203,7 +1203,7 @@ class CookieAccessSchemeHandlerFactory : public CefSchemeHandlerFactory,
const std::string& url = request->GetURL();
ResponseDataMap::const_iterator it = data_map_.find(url);
if (it != data_map_.end()) {
it->second->got_request_.yes();
it->second->request_ct_++;
return new CookieAccessSchemeHandler(it->second);
}
@@ -1425,13 +1425,13 @@ class CookieAccessServerHandler : public CefServerHandler,
const std::string& url = request->GetURL();
ResponseDataMap::const_iterator it = data_map_.find(url);
if (it != data_map_.end()) {
it->second->got_request_.yes();
it->second->request_ct_++;
CefRequest::HeaderMap headerMap;
request->GetHeaderMap(headerMap);
const std::string& cookie_str = GetHeaderValue(headerMap, "cookie");
TestCookieString(cookie_str, it->second->got_cookie_js_,
it->second->got_cookie_net_);
TestCookieString(cookie_str, it->second->cookie_js_ct_,
it->second->cookie_net_ct_);
SendResponse(server, connection_id, it->second->response,
it->second->response_data);
@@ -1593,10 +1593,8 @@ class CookieAccessTestHandler : public RoutingTestHandler,
context_ = NULL;
// Got both network requests.
EXPECT_TRUE(data1_.got_request_);
EXPECT_TRUE(data2_.got_request_);
EXPECT_FALSE(got_cookie_manager_);
EXPECT_EQ(1, data1_.request_ct_);
EXPECT_EQ(1, data2_.request_ct_);
if (test_mode_ == ALLOW_NO_FILTER || test_mode_ == ALLOW_NO_HANDLER) {
EXPECT_EQ(0, can_save_cookie1_ct_);
@@ -1621,44 +1619,44 @@ class CookieAccessTestHandler : public RoutingTestHandler,
if (test_mode_ == BLOCK_ALL_COOKIES) {
// Never get the JS cookie via JS.
EXPECT_FALSE(got_cookie_js1_);
EXPECT_FALSE(got_cookie_js2_);
EXPECT_FALSE(got_cookie_js3_);
EXPECT_EQ(0, cookie_js1_ct_);
EXPECT_EQ(0, cookie_js2_ct_);
EXPECT_EQ(0, cookie_js3_ct_);
} else {
// Always get the JS cookie via JS.
EXPECT_TRUE(got_cookie_js1_);
EXPECT_TRUE(got_cookie_js2_);
EXPECT_TRUE(got_cookie_js3_);
EXPECT_EQ(1, cookie_js1_ct_);
EXPECT_EQ(1, cookie_js2_ct_);
EXPECT_EQ(1, cookie_js3_ct_);
}
// Only get the net cookie via JS if cookie write was allowed.
if ((test_mode_ & BLOCK_WRITE) || test_mode_ == BLOCK_ALL_COOKIES) {
EXPECT_FALSE(got_cookie_net1_);
EXPECT_FALSE(got_cookie_net2_);
EXPECT_FALSE(got_cookie_net3_);
EXPECT_EQ(0, cookie_net1_ct_);
EXPECT_EQ(0, cookie_net2_ct_);
EXPECT_EQ(0, cookie_net3_ct_);
} else {
EXPECT_TRUE(got_cookie_net1_);
EXPECT_TRUE(got_cookie_net2_);
EXPECT_TRUE(got_cookie_net3_);
EXPECT_EQ(1, cookie_net1_ct_);
EXPECT_EQ(1, cookie_net2_ct_);
EXPECT_EQ(1, cookie_net3_ct_);
}
// No cookies sent for the 1st network request.
EXPECT_FALSE(data1_.got_cookie_js_);
EXPECT_FALSE(data1_.got_cookie_net_);
EXPECT_EQ(0, data1_.cookie_js_ct_);
EXPECT_EQ(0, data1_.cookie_net_ct_);
// 2nd network request...
if ((test_mode_ & BLOCK_READ) || test_mode_ == BLOCK_ALL_COOKIES) {
// No cookies sent if reading was blocked.
EXPECT_FALSE(data2_.got_cookie_js_);
EXPECT_FALSE(data2_.got_cookie_net_);
EXPECT_EQ(0, data2_.cookie_js_ct_);
EXPECT_EQ(0, data2_.cookie_net_ct_);
} else if (test_mode_ & BLOCK_WRITE) {
// Only JS cookie sent if writing was blocked.
EXPECT_TRUE(data2_.got_cookie_js_);
EXPECT_FALSE(data2_.got_cookie_net_);
EXPECT_EQ(1, data2_.cookie_js_ct_);
EXPECT_EQ(0, data2_.cookie_net_ct_);
} else {
// All cookies sent.
EXPECT_TRUE(data2_.got_cookie_js_);
EXPECT_TRUE(data2_.got_cookie_net_);
EXPECT_EQ(1, data2_.cookie_js_ct_);
EXPECT_EQ(1, data2_.cookie_net_ct_);
}
TestHandler::DestroyTest();
@@ -1747,11 +1745,11 @@ class CookieAccessTestHandler : public RoutingTestHandler,
const std::string& url = frame->GetURL();
const std::string& cookie_str = request.ToString();
if (url == GetCookieAccessUrl1(scheme_, test_backend_ == SERVER)) {
TestCookieString(cookie_str, got_cookie_js1_, got_cookie_net1_);
TestCookieString(cookie_str, cookie_js1_ct_, cookie_net1_ct_);
browser->GetMainFrame()->LoadURL(
GetCookieAccessUrl2(scheme_, test_backend_ == SERVER));
} else if (url == GetCookieAccessUrl2(scheme_, test_backend_ == SERVER)) {
TestCookieString(cookie_str, got_cookie_js2_, got_cookie_net2_);
TestCookieString(cookie_str, cookie_js2_ct_, cookie_net2_ct_);
FinishTest();
} else {
ADD_FAILURE() << "Unexpected url: " << url;
@@ -1873,9 +1871,9 @@ class CookieAccessTestHandler : public RoutingTestHandler,
const std::string& name = CefString(&cookie.name);
const std::string& value = CefString(&cookie.value);
if (name == "name_js" && value == "value_js")
handler_->got_cookie_js3_.yes();
handler_->cookie_js3_ct_++;
else if (name == "name_net" && value == "value_net")
handler_->got_cookie_net3_.yes();
handler_->cookie_net3_ct_++;
// Clean up the cookies.
deleteCookie = true;
@@ -1930,21 +1928,19 @@ class CookieAccessTestHandler : public RoutingTestHandler,
CookieAccessData data1_;
CookieAccessData data2_;
TrackCallback got_cookie_manager_;
// 1st request.
int can_save_cookie1_ct_ = 0;
TrackCallback got_cookie_js1_;
TrackCallback got_cookie_net1_;
int cookie_js1_ct_ = 0;
int cookie_net1_ct_ = 0;
// 2nd request.
int can_send_cookie2_ct_ = 0;
TrackCallback got_cookie_js2_;
TrackCallback got_cookie_net2_;
int cookie_js2_ct_ = 0;
int cookie_net2_ct_ = 0;
// From cookie manager.
TrackCallback got_cookie_js3_;
TrackCallback got_cookie_net3_;
int cookie_js3_ct_ = 0;
int cookie_net3_ct_ = 0;
DISALLOW_COPY_AND_ASSIGN(CookieAccessTestHandler);
IMPLEMENT_REFCOUNTING(CookieAccessTestHandler);
@@ -2026,6 +2022,397 @@ ACCESS_TEST_ALLOWNOHANDLER_MODES(SchemeStandard, SCHEME_HANDLER, false)
ACCESS_TEST_CUSTOM(Resource, RESOURCE_HANDLER)
ACCESS_TEST_STANDARD(Resource, RESOURCE_HANDLER)
namespace {
// Tests the behavior of restarting of a network request that sets cookies and
// a network request that includes cookies.
// 1. Begin loading URL1, then restart the request in OnResourceResponse.
// No cookies are saved.
// 2. Load URL1 successfully. Network and JS cookies are saved.
// 3. Begin loading URL2, then restart the request in OnResourceResponse.
// Cookies are sent with the request/response.
// 4. Load URL2 successfully. Cookies are sent with the request/response.
class CookieRestartTestHandler : public RoutingTestHandler,
public CefCookieAccessFilter {
public:
explicit CookieRestartTestHandler(bool use_global)
: scheme_(kCookieAccessScheme), use_global_(use_global) {}
void RunTest() override {
if (use_global_) {
context_ = CefRequestContext::GetGlobalContext();
} else {
// Create the request context that will use an in-memory cache.
CefRequestContextSettings settings;
context_ = CefRequestContext::CreateContext(settings, NULL);
}
cookie_manager_ = context_->GetCookieManager(nullptr);
SetTestTimeout();
RunTestSetupContinue();
}
void DestroyTest() override {
if (!CefCurrentlyOn(TID_UI)) {
CefPostTask(TID_UI,
base::Bind(&CookieRestartTestHandler::DestroyTest, this));
return;
}
cookie_manager_ = NULL;
context_ = NULL;
// Get 2 network requests for each URL.
EXPECT_EQ(2, data1_.request_ct_);
EXPECT_EQ(2, data2_.request_ct_);
// Get resource request callbacks for all requests (2 for each URL).
EXPECT_EQ(4, before_resource_load_ct_);
EXPECT_EQ(4, resource_response_ct_);
// Get JS query callbacks for the successful requests (1 for each URL).
EXPECT_EQ(2, query_ct_);
// No cookies sent for the URL1 network requests because (a) we don't have
// any cookies set initially and (b) we don't save cookies from the 1st URL1
// request which is restarted.
EXPECT_EQ(0, data1_.cookie_js_ct_);
EXPECT_EQ(0, data1_.cookie_net_ct_);
// Net and JS cookies sent for both URL2 network requests.
EXPECT_EQ(2, data2_.cookie_js_ct_);
EXPECT_EQ(2, data2_.cookie_net_ct_);
// 1 call to CanSaveCookie for the net cookie returned by the successful
// URL1 request.
EXPECT_EQ(1, can_save_cookie_ct_);
// 4 calls to CanSendCookie because both net and JS cookies are sent for
// each URL2 request.
EXPECT_EQ(4, can_send_cookie_ct_);
// Get the net and JS cookies from the JS query for the successful requests
// (1 for each URL).
EXPECT_EQ(1, cookie_js1_ct_);
EXPECT_EQ(1, cookie_net1_ct_);
EXPECT_EQ(1, cookie_js2_ct_);
EXPECT_EQ(1, cookie_net2_ct_);
// Get the net and JS cookies from the cookie manager at the end.
EXPECT_EQ(1, cookie_manager_js_ct_);
EXPECT_EQ(1, cookie_manager_net_ct_);
TestHandler::DestroyTest();
}
CefRefPtr<CefCookieAccessFilter> GetCookieAccessFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override {
EXPECT_IO_THREAD();
return this;
}
CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_navigation,
bool is_download,
const CefString& request_initiator,
bool& disable_default_handling) override {
return this;
}
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override {
return nullptr;
}
bool CanSendCookie(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
const CefCookie& cookie) override {
EXPECT_IO_THREAD();
can_send_cookie_ct_++;
// Called before the URL2 network requests.
EXPECT_LE(2, before_resource_load_ct_);
return true;
}
bool CanSaveCookie(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response,
const CefCookie& cookie) override {
EXPECT_IO_THREAD();
can_save_cookie_ct_++;
// Called after the successful URL1 network request.
EXPECT_EQ(2, before_resource_load_ct_);
// Expecting the network cookie only.
EXPECT_STREQ("name_net", CefString(&cookie.name).ToString().c_str());
EXPECT_STREQ("value_net", CefString(&cookie.value).ToString().c_str());
return true;
}
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefRequestCallback> callback) override {
EXPECT_IO_THREAD();
before_resource_load_ct_++;
const std::string& url = request->GetURL();
if (before_resource_load_ct_ <= 2) {
EXPECT_STREQ(GetCookieAccessUrl1(scheme_, true).c_str(), url.c_str());
} else {
EXPECT_STREQ(GetCookieAccessUrl2(scheme_, true).c_str(), url.c_str());
}
const std::string& cookie_str = request->GetHeaderByName("Cookie");
int cookie_js_ct = 0;
int cookie_net_ct = 0;
TestCookieString(cookie_str, cookie_js_ct, cookie_net_ct);
// Expect both cookies with the URL2 requests only.
if (before_resource_load_ct_ >= 3) {
EXPECT_EQ(1, cookie_js_ct);
EXPECT_EQ(1, cookie_net_ct);
} else {
EXPECT_EQ(0, cookie_js_ct);
EXPECT_EQ(0, cookie_net_ct);
}
return RV_CONTINUE;
}
bool OnResourceResponse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override {
EXPECT_IO_THREAD();
resource_response_ct_++;
const std::string& url = request->GetURL();
const std::string& set_cookie_str = response->GetHeader("Set-Cookie");
// Expect the network cookie with URL1 requests only.
if (resource_response_ct_ <= 2) {
EXPECT_STREQ(GetCookieAccessUrl1(scheme_, true).c_str(), url.c_str());
EXPECT_STREQ("name_net=value_net", set_cookie_str.c_str());
} else {
EXPECT_STREQ(GetCookieAccessUrl2(scheme_, true).c_str(), url.c_str());
EXPECT_TRUE(set_cookie_str.empty());
}
if (resource_response_ct_ == 1 || resource_response_ct_ == 3) {
// Restart the request loading this data.
request->SetHeaderByName("X-Custom-Header", "value", false);
return true;
}
return false;
}
bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) override {
query_ct_++;
const std::string& url = frame->GetURL();
const std::string& cookie_str = request.ToString();
if (url == GetCookieAccessUrl1(scheme_, true)) {
TestCookieString(cookie_str, cookie_js1_ct_, cookie_net1_ct_);
browser->GetMainFrame()->LoadURL(GetCookieAccessUrl2(scheme_, true));
} else if (url == GetCookieAccessUrl2(scheme_, true)) {
TestCookieString(cookie_str, cookie_js2_ct_, cookie_net2_ct_);
FinishTest();
} else {
ADD_FAILURE() << "Unexpected url: " << url;
}
return true;
}
private:
void AddResponses(CookieAccessResponseHandler* handler) {
// Sets a cookie via net response headers and JS, then retrieves the cookies
// via JS.
{
data1_.response = CefResponse::Create();
data1_.response->SetMimeType("text/html");
data1_.response->SetStatus(200);
data1_.response->SetStatusText("OK");
CefResponse::HeaderMap headerMap;
data1_.response->GetHeaderMap(headerMap);
headerMap.insert(std::make_pair("Set-Cookie", "name_net=value_net"));
data1_.response->SetHeaderMap(headerMap);
data1_.response_data =
"<html><head>"
"<script>"
"document.cookie='name_js=value_js';"
"window.testQuery({request:document.cookie});"
"</script>"
"</head><body>COOKIE RESTART TEST1</body></html>";
handler->AddResponse(GetCookieAccessUrl1(scheme_, true), &data1_);
}
// Retrieves the cookies via JS.
{
data2_.response = CefResponse::Create();
data2_.response->SetMimeType("text/html");
data2_.response->SetStatus(200);
data2_.response->SetStatusText("OK");
data2_.response_data =
"<html><head>"
"<script>"
"window.testQuery({request:document.cookie});"
"</script>"
"</head><body>COOKIE RESTART TEST2</body></html>";
handler->AddResponse(GetCookieAccessUrl2(scheme_, true), &data2_);
}
}
void RunTestSetupContinue() {
CefPostTask(
TID_UI,
base::Bind(
&CookieRestartTestHandler::StartServer, this,
base::Bind(&CookieRestartTestHandler::RunTestContinue, this)));
}
void StartServer(const base::Closure& complete_callback) {
EXPECT_FALSE(server_handler_);
server_handler_ = new CookieAccessServerHandler();
AddResponses(server_handler_.get());
// 2 requests for each URL.
server_handler_->SetExpectedRequestCount(4);
server_handler_->CreateServer(complete_callback);
}
void RunTestContinue() {
if (!CefCurrentlyOn(TID_UI)) {
CefPostTask(TID_UI,
base::Bind(&CookieRestartTestHandler::RunTestContinue, this));
return;
}
CreateBrowser(GetCookieAccessUrl1(scheme_, true), context_);
}
void FinishTest() {
// Verify that cookies were set correctly.
class TestVisitor : public CefCookieVisitor {
public:
explicit TestVisitor(CookieRestartTestHandler* handler)
: handler_(handler) {}
~TestVisitor() override {
// Destroy the test.
CefPostTask(
TID_UI,
base::Bind(
&CookieRestartTestHandler::ShutdownServer, handler_,
base::Bind(&CookieRestartTestHandler::DestroyTest, handler_)));
}
bool Visit(const CefCookie& cookie,
int count,
int total,
bool& deleteCookie) override {
const std::string& name = CefString(&cookie.name);
const std::string& value = CefString(&cookie.value);
if (name == "name_js" && value == "value_js")
handler_->cookie_manager_js_ct_++;
else if (name == "name_net" && value == "value_net")
handler_->cookie_manager_net_ct_++;
// Clean up the cookies.
deleteCookie = true;
return true;
}
private:
CookieRestartTestHandler* handler_;
IMPLEMENT_REFCOUNTING(TestVisitor);
};
cookie_manager_->VisitAllCookies(new TestVisitor(this));
}
void ShutdownServer(const base::Closure& complete_callback) {
EXPECT_TRUE(server_handler_);
server_handler_->ShutdownServer(complete_callback);
server_handler_ = nullptr;
}
const std::string scheme_;
const bool use_global_;
CefRefPtr<CefRequestContext> context_;
CefRefPtr<CefCookieManager> cookie_manager_;
CefRefPtr<CookieAccessServerHandler> server_handler_;
CookieAccessData data1_;
CookieAccessData data2_;
int before_resource_load_ct_ = 0;
int resource_response_ct_ = 0;
int query_ct_ = 0;
// From network requests.
int can_save_cookie_ct_ = 0;
int can_send_cookie_ct_ = 0;
int cookie_js1_ct_ = 0;
int cookie_net1_ct_ = 0;
int cookie_js2_ct_ = 0;
int cookie_net2_ct_ = 0;
// From cookie manager.
int cookie_manager_js_ct_ = 0;
int cookie_manager_net_ct_ = 0;
DISALLOW_COPY_AND_ASSIGN(CookieRestartTestHandler);
IMPLEMENT_REFCOUNTING(CookieRestartTestHandler);
};
} // namespace
TEST(CookieTest, RestartGlobal) {
if (!IsNetworkServiceEnabled())
return;
CefRefPtr<CookieRestartTestHandler> handler =
new CookieRestartTestHandler(true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
TEST(CookieTest, RestartInMemory) {
if (!IsNetworkServiceEnabled())
return;
CefRefPtr<CookieRestartTestHandler> handler =
new CookieRestartTestHandler(false);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Entry point for registering custom schemes.
// Called from client_app_delegates.cc.
void RegisterCookieCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar,

View File

@@ -393,6 +393,11 @@ class FrameNavRendererTest : public ClientAppRenderer::Delegate,
EXPECT_TRUE(args.get());
EXPECT_TRUE(args->SetInt(0, nav_));
EXPECT_TRUE(args->SetBool(1, result));
const int64 frame_id = frame->GetIdentifier();
EXPECT_TRUE(args->SetInt(2, CefInt64GetLow(frame_id)));
EXPECT_TRUE(args->SetInt(3, CefInt64GetHigh(frame_id)));
frame->SendProcessMessage(PID_BROWSER, return_msg);
nav_++;
@@ -527,6 +532,11 @@ class FrameNavTestHandler : public TestHandler {
EXPECT_TRUE(expectations_->OnRendererComplete(
browser, frame, args->GetInt(0), args->GetBool(1)))
<< "nav = " << nav_;
// Test that browser and render process frame IDs match.
const int64 frame_id = CefInt64Set(args->GetInt(2), args->GetInt(3));
EXPECT_EQ(frame->GetIdentifier(), frame_id);
return true;
}

View File

@@ -163,6 +163,14 @@ class BasicResponseTest : public TestHandler {
// Normal load, nothing fancy.
LOAD,
// Close the browser in OnAfterCreated to verify destruction handling of
// uninitialized requests.
ABORT_AFTER_CREATED,
// Close the browser in OnBeforeBrowse to verify destruction handling of
// uninitialized requests.
ABORT_BEFORE_BROWSE,
// Don't continue from OnBeforeResourceLoad, then close the browser to
// verify destruction handling of in-progress requests.
INCOMPLETE_BEFORE_RESOURCE_LOAD,
@@ -207,6 +215,25 @@ class BasicResponseTest : public TestHandler {
SetTestTimeout();
}
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
EXPECT_UI_THREAD();
TestHandler::OnAfterCreated(browser);
if (mode_ == ABORT_AFTER_CREATED) {
SetSignalCompletionWhenAllBrowsersClose(false);
CloseBrowser(browser, false);
}
}
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
EXPECT_UI_THREAD();
TestHandler::OnBeforeClose(browser);
if (IsAborted()) {
DestroyTest();
}
}
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
@@ -233,6 +260,11 @@ class BasicResponseTest : public TestHandler {
VerifyState(kOnBeforeBrowse, request, nullptr);
if (mode_ == ABORT_BEFORE_BROWSE) {
SetSignalCompletionWhenAllBrowsersClose(false);
CloseBrowser(browser, false);
}
return false;
}
@@ -475,7 +507,7 @@ class BasicResponseTest : public TestHandler {
VerifyState(kOnResourceLoadComplete, request, response);
if (unhandled_ || IsIncomplete()) {
if (unhandled_ || IsIncomplete() || IsAborted()) {
EXPECT_EQ(UR_FAILED, status);
EXPECT_EQ(0, received_content_length);
} else {
@@ -661,19 +693,36 @@ class BasicResponseTest : public TestHandler {
EXPECT_EQ(0, get_resource_response_filter_ct_);
EXPECT_EQ(0, on_resource_response_ct_);
}
} else if (IsAborted()) {
EXPECT_EQ(1, on_before_browse_ct_);
if (custom_scheme_) {
EXPECT_EQ(0, get_resource_request_handler_ct_);
EXPECT_EQ(0, get_cookie_access_filter_ct_);
} else {
// The callbacks executed for standard schemes may vary based on timing.
}
EXPECT_EQ(0, on_before_resource_load_ct_);
EXPECT_EQ(0, get_resource_handler_ct_);
EXPECT_EQ(0, on_resource_redirect_ct_);
EXPECT_EQ(0, get_resource_response_filter_ct_);
EXPECT_EQ(0, on_resource_response_ct_);
} else {
NOTREACHED();
}
EXPECT_EQ(resource_handler_created_ct_, resource_handler_destroyed_ct_);
EXPECT_EQ(1, on_resource_load_complete_ct_);
if (IsIncomplete())
if (IsAborted())
EXPECT_EQ(0, on_resource_load_complete_ct_);
else
EXPECT_EQ(1, on_resource_load_complete_ct_);
if (IsIncomplete() || IsAborted())
EXPECT_EQ(0, on_load_end_ct_);
else
EXPECT_EQ(1, on_load_end_ct_);
if (custom_scheme_ && unhandled_ && !IsIncomplete())
if (custom_scheme_ && unhandled_ && !(IsIncomplete() || IsAborted()))
EXPECT_EQ(1, on_protocol_execution_ct_);
else
EXPECT_EQ(0, on_protocol_execution_ct_);
@@ -715,7 +764,7 @@ class BasicResponseTest : public TestHandler {
}
const char* GetStartupURL() const {
if (IsLoad() || IsIncomplete()) {
if (IsLoad() || IsIncomplete() || IsAborted()) {
return GetURL(RESULT_HTML);
} else if (mode_ == REDIRECT_RESOURCE_REDIRECT) {
return GetURL(REDIRECT2_HTML);
@@ -786,6 +835,10 @@ class BasicResponseTest : public TestHandler {
IsIncompleteRequestHandler();
}
bool IsAborted() const {
return mode_ == ABORT_AFTER_CREATED || mode_ == ABORT_BEFORE_BROWSE;
}
bool IsRedirect() const {
return mode_ == REDIRECT_BEFORE_RESOURCE_LOAD ||
mode_ == REDIRECT_REQUEST_HANDLER ||
@@ -852,7 +905,7 @@ class BasicResponseTest : public TestHandler {
EXPECT_EQ(request_id_, request->GetIdentifier()) << callback;
}
if (IsLoad() || IsIncomplete()) {
if (IsLoad() || IsIncomplete() || IsAborted()) {
EXPECT_STREQ("GET", request->GetMethod().ToString().c_str()) << callback;
EXPECT_STREQ(GetURL(RESULT_HTML), request->GetURL().ToString().c_str())
<< callback;
@@ -912,7 +965,8 @@ class BasicResponseTest : public TestHandler {
// response.
const bool incomplete_unhandled =
(mode_ == INCOMPLETE_BEFORE_RESOURCE_LOAD ||
mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST);
mode_ == INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST ||
(IsAborted() && !custom_scheme_));
if ((unhandled_ && !override_unhandled) || incomplete_unhandled) {
if (incomplete_unhandled) {
@@ -927,7 +981,7 @@ class BasicResponseTest : public TestHandler {
EXPECT_STREQ("", response->GetMimeType().ToString().c_str()) << callback;
EXPECT_STREQ("", response->GetCharset().ToString().c_str()) << callback;
} else {
if (mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE &&
if ((mode_ == INCOMPLETE_REQUEST_HANDLER_READ_RESPONSE || IsAborted()) &&
callback == kOnResourceLoadComplete) {
// We got a response, but we also got aborted.
EXPECT_EQ(ERR_ABORTED, response->GetError()) << callback;
@@ -1035,7 +1089,9 @@ bool IsTestSupported(BasicResponseTest::TestMode test_mode,
// for custom schemes and unhandled requests.
return false;
}
if (test_mode == BasicResponseTest::INCOMPLETE_BEFORE_RESOURCE_LOAD ||
if (test_mode == BasicResponseTest::ABORT_AFTER_CREATED ||
test_mode == BasicResponseTest::ABORT_BEFORE_BROWSE ||
test_mode == BasicResponseTest::INCOMPLETE_BEFORE_RESOURCE_LOAD ||
test_mode ==
BasicResponseTest::INCOMPLETE_REQUEST_HANDLER_PROCESS_REQUEST ||
test_mode ==
@@ -1063,6 +1119,8 @@ bool IsTestSupported(BasicResponseTest::TestMode test_mode,
#define BASIC_TEST_ALL_MODES(name, custom, unhandled) \
BASIC_TEST(name##Load, LOAD, custom, unhandled) \
BASIC_TEST(name##AbortAfterCreated, ABORT_AFTER_CREATED, custom, unhandled) \
BASIC_TEST(name##AbortBeforeBrowse, ABORT_BEFORE_BROWSE, custom, unhandled) \
BASIC_TEST(name##ModifyBeforeResourceLoad, MODIFY_BEFORE_RESOURCE_LOAD, \
custom, unhandled) \
BASIC_TEST(name##RedirectBeforeResourceLoad, REDIRECT_BEFORE_RESOURCE_LOAD, \

View File

@@ -450,6 +450,11 @@ void TestHandler::SetTestTimeout(int timeout_ms, bool treat_as_error) {
return;
}
if (destroy_test_called_) {
// No need to set the timeout if the test has already completed.
return;
}
if (treat_as_error && CefCommandLine::GetGlobalCommandLine()->HasSwitch(
"disable-test-timeout")) {
return;
@@ -475,7 +480,7 @@ void TestHandler::TestComplete() {
TestHandler::UIThreadHelper* TestHandler::GetUIThreadHelper() {
EXPECT_UI_THREAD();
EXPECT_FALSE(destroy_test_called_);
CHECK(!destroy_test_called_);
if (!ui_thread_helper_.get())
ui_thread_helper_.reset(new UIThreadHelper());

View File

@@ -7,6 +7,7 @@
#include <sstream>
#include "include/base/cef_bind.h"
#include "include/cef_parser.h"
#include "include/cef_request_context_handler.h"
#include "include/cef_scheme.h"
#include "include/cef_server.h"
@@ -65,9 +66,12 @@ enum RequestTestMode {
REQTEST_GET_REDIRECT_STOP,
REQTEST_GET_REDIRECT_LOCATION,
REQTEST_GET_REFERRER,
REQTEST_GET_AUTH,
REQTEST_POST,
REQTEST_POST_FILE,
REQTEST_POST_WITHPROGRESS,
REQTEST_POST_REDIRECT,
REQTEST_POST_REDIRECT_TOGET,
REQTEST_HEAD,
REQTEST_CACHE_WITH_CONTROL,
REQTEST_CACHE_WITHOUT_CONTROL,
@@ -142,6 +146,16 @@ struct RequestRunSettings {
// If true the response cookie should be saved.
bool expect_save_cookie = false;
// If true the test will begin by requiring Basic authentication and then
// continue with the actual request. The UR_FLAG_ALLOW_STORED_CREDENTIALS
// flag must be set on the request. When using the global request context
// CefRequestContext::ClearHttpAuthCredentials should be called to avoid
// leaking state across test runs. Authentication is only supported with
// browser-initiated requests and the server backend.
bool expect_authentication = false;
std::string username;
std::string password;
// If specified the test will begin with this redirect request and response.
CefRefPtr<CefRequest> redirect_request;
CefRefPtr<CefResponse> redirect_response;
@@ -264,6 +278,24 @@ class RequestDataMap {
RedirectDataMap redirect_data_map_;
};
class TestCompletionCallback : public CefCompletionCallback {
public:
explicit TestCompletionCallback(const base::Closure& complete_callback)
: complete_callback_(complete_callback) {
EXPECT_FALSE(complete_callback_.is_null());
}
void OnComplete() override {
complete_callback_.Run();
complete_callback_.Reset();
}
private:
base::Closure complete_callback_;
IMPLEMENT_REFCOUNTING(TestCompletionCallback);
};
std::string GetRequestScheme(bool server_backend) {
return server_backend ? kRequestSchemeServer : kRequestSchemeCustom;
}
@@ -470,6 +502,47 @@ void GetNormalResponse(const RequestRunSettings* settings,
response->SetHeaderMap(headerMap);
}
// Based on https://en.wikipedia.org/wiki/Basic_access_authentication#Protocol
void GetAuthResponse(CefRefPtr<CefResponse> response) {
response->SetStatus(401);
response->SetStatusText("Unauthorized");
response->SetMimeType("text/html");
CefResponse::HeaderMap headerMap;
headerMap.insert(
std::make_pair("WWW-Authenticate", "Basic realm=\"Test Realm\""));
response->SetHeaderMap(headerMap);
}
bool IsAuthorized(CefRefPtr<CefRequest> request,
const std::string& username,
const std::string& password) {
const std::string& authHeader = request->GetHeaderByName("Authorization");
if (authHeader.empty())
return false;
if (authHeader.find("Basic ") == 0) {
const std::string& base64 = authHeader.substr(6);
CefRefPtr<CefBinaryValue> data = CefBase64Decode(base64);
EXPECT_TRUE(data);
if (!data) {
LOG(ERROR) << "Failed to decode Authorization value: " << base64;
return false;
}
std::string decoded;
decoded.resize(data->GetSize());
data->GetData(&decoded[0], data->GetSize(), 0);
const std::string& expected = username + ":" + password;
EXPECT_STREQ(expected.c_str(), decoded.c_str());
return decoded == expected;
}
LOG(ERROR) << "Unexpected Authorization value: " << authHeader;
return false;
}
// SCHEME HANDLER BACKEND
// Serves request responses.
@@ -1007,6 +1080,14 @@ class RequestServerHandler : public CefServerHandler {
CefRefPtr<CefRequest> request) {
RequestDataMap::Entry entry = data_map_.Find(request->GetURL());
if (entry.type == RequestDataMap::Entry::TYPE_NORMAL) {
const bool needs_auth = entry.settings->expect_authentication &&
!IsAuthorized(request, entry.settings->username,
entry.settings->password);
if (needs_auth) {
HandleAuthRequest(server, connection_id, request);
return;
}
HandleNormalRequest(server, connection_id, request, entry.settings);
} else if (entry.type == RequestDataMap::Entry::TYPE_REDIRECT) {
HandleRedirectRequest(server, connection_id, request,
@@ -1018,6 +1099,14 @@ class RequestServerHandler : public CefServerHandler {
}
}
void HandleAuthRequest(CefRefPtr<CefServer> server,
int connection_id,
CefRefPtr<CefRequest> request) {
CefRefPtr<CefResponse> response = CefResponse::Create();
GetAuthResponse(response);
SendResponse(server, connection_id, response, std::string());
}
void HandleNormalRequest(CefRefPtr<CefServer> server,
int connection_id,
CefRefPtr<CefRequest> request,
@@ -1185,6 +1274,11 @@ class RequestClient : public CefURLRequestClient {
const CefString& realm,
const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) override {
auth_credentials_ct_++;
if (has_authentication_) {
callback->Continue(username_, password_);
return true;
}
return false;
}
@@ -1192,10 +1286,15 @@ class RequestClient : public CefURLRequestClient {
const RequestCompleteCallback complete_callback_;
public:
bool has_authentication_ = false;
std::string username_;
std::string password_;
int request_complete_ct_ = 0;
int upload_progress_ct_ = 0;
int download_progress_ct_ = 0;
int download_data_ct_ = 0;
int auth_credentials_ct_ = 0;
int64 upload_total_ = 0;
int64 download_total_ = 0;
@@ -1247,10 +1346,14 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
REGISTER_TEST(REQTEST_GET_REDIRECT_LOCATION, SetupGetRedirectLocationTest,
SingleRunTest);
REGISTER_TEST(REQTEST_GET_REFERRER, SetupGetReferrerTest, SingleRunTest);
REGISTER_TEST(REQTEST_GET_AUTH, SetupGetAuthTest, SingleRunTest);
REGISTER_TEST(REQTEST_POST, SetupPostTest, SingleRunTest);
REGISTER_TEST(REQTEST_POST_FILE, SetupPostFileTest, SingleRunTest);
REGISTER_TEST(REQTEST_POST_WITHPROGRESS, SetupPostWithProgressTest,
SingleRunTest);
REGISTER_TEST(REQTEST_POST_REDIRECT, SetupPostRedirectTest, SingleRunTest);
REGISTER_TEST(REQTEST_POST_REDIRECT_TOGET, SetupPostRedirectToGetTest,
SingleRunTest);
REGISTER_TEST(REQTEST_HEAD, SetupHeadTest, SingleRunTest);
REGISTER_TEST(REQTEST_CACHE_WITH_CONTROL, SetupCacheWithControlTest,
MultipleRunTest);
@@ -1523,6 +1626,28 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
complete_callback.Run();
}
void SetupGetAuthTest(const base::Closure& complete_callback) {
// Start with the normal get test.
SetupGetTestShared();
// Require Basic authentication.
settings_.expect_authentication = true;
settings_.username = "user";
settings_.password = "pass";
// This flag is required to support credentials, which means we'll also get
// the cookies.
settings_.request->SetFlags(UR_FLAG_ALLOW_STORED_CREDENTIALS);
settings_.expect_save_cookie = true;
settings_.expect_send_cookie = true;
// The authentication request will come first, then the actual request.
settings_.expected_receive_count = 2;
settings_.expected_send_count = 2;
complete_callback.Run();
}
void SetupPostTestShared() {
settings_.request = CefRequest::Create();
settings_.request->SetURL(GetTestURL("PostTest.html"));
@@ -1589,6 +1714,58 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
complete_callback.Run();
}
void SetupPostRedirectTest(const base::Closure& complete_callback) {
// Start with the normal post test.
SetupPostTestShared();
// Add a redirect request.
settings_.redirect_request = CefRequest::Create();
settings_.redirect_request->SetURL(GetTestURL("redirect.html"));
settings_.redirect_request->SetMethod("POST");
SetUploadData(settings_.redirect_request, "the_post_data");
settings_.redirect_response = CefResponse::Create();
settings_.redirect_response->SetMimeType("text/html");
// Only 307 is supported for redirecting the same method and post data.
settings_.redirect_response->SetStatus(307);
settings_.redirect_response->SetStatusText("Found");
CefResponse::HeaderMap headerMap;
headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
settings_.redirect_response->SetHeaderMap(headerMap);
complete_callback.Run();
}
void SetupPostRedirectToGetTest(const base::Closure& complete_callback) {
// Start with the normal post test.
SetupPostTestShared();
// The expected result after redirect is a GET request without POST data.
settings_.request = CefRequest::Create();
settings_.request->SetURL(GetTestURL("PostTest.html"));
settings_.request->SetMethod("GET");
// Add a redirect request.
settings_.redirect_request = CefRequest::Create();
settings_.redirect_request->SetURL(GetTestURL("redirect.html"));
settings_.redirect_request->SetMethod("POST");
SetUploadData(settings_.redirect_request, "the_post_data");
settings_.redirect_response = CefResponse::Create();
settings_.redirect_response->SetMimeType("text/html");
// Redirect codes other than 307 will cause conversion to GET and removal
// of POST data.
settings_.redirect_response->SetStatus(302);
settings_.redirect_response->SetStatusText("Found");
CefResponse::HeaderMap headerMap;
headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
settings_.redirect_response->SetHeaderMap(headerMap);
complete_callback.Run();
}
void SetupHeadTest(const base::Closure& complete_callback) {
settings_.request = CefRequest::Create();
settings_.request->SetURL(GetTestURL("HeadTest.html"));
@@ -1994,6 +2171,16 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
EXPECT_TRUE(request.get());
CefRefPtr<RequestClient> client = new RequestClient(complete_callback);
// Delegation to CefRequestHandler::GetAuthCredentials is only supported
// with NetworkService.
if ((!IsNetworkServiceEnabled() || !use_frame_method_) &&
settings_.expect_authentication) {
client->has_authentication_ = true;
client->username_ = settings_.username;
client->password_ = settings_.password;
}
if (use_frame_method_) {
EXPECT_TRUE(frame_);
frame_->CreateURLRequest(request, client.get());
@@ -2064,6 +2251,12 @@ class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
EXPECT_EQ(0, client->download_data_ct_);
EXPECT_TRUE(client->download_data_.empty());
}
if (settings_.expect_authentication) {
EXPECT_EQ(1, client->auth_credentials_ct_);
} else {
EXPECT_EQ(0, client->auth_credentials_ct_);
}
}
// Run a test with a single request.
@@ -2471,7 +2664,7 @@ class RequestTestHandler : public TestHandler {
// Continue the test once supported schemes has been set.
request_context->GetCookieManager(NULL)->SetSupportedSchemes(
supported_schemes, true,
new SupportedSchemesCompletionCallback(
new TestCompletionCallback(
base::Bind(&RequestTestHandler::PreSetupComplete, this)));
} else {
PreSetupComplete();
@@ -2544,6 +2737,25 @@ class RequestTestHandler : public TestHandler {
return TestHandler::OnBeforeResourceLoad(browser, frame, request, callback);
}
bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
bool isProxy,
const CefString& host,
int port,
const CefString& realm,
const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) override {
EXPECT_TRUE(test_in_browser_);
EXPECT_TRUE(test_frame_method_);
auth_credentials_ct_++;
if (test_runner_->settings_.expect_authentication) {
callback->Continue(test_runner_->settings_.username,
test_runner_->settings_.password);
return true;
}
return false;
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
@@ -2654,7 +2866,21 @@ class RequestTestHandler : public TestHandler {
// Shut down the browser side of the test.
test_runner_->ShutdownTest(
base::Bind(&RequestTestHandler::DestroyTest, this));
base::Bind(&RequestTestHandler::MaybeClearAuthCredentials, this));
}
void MaybeClearAuthCredentials() {
if (test_runner_->settings_.expect_authentication &&
context_mode_ == CONTEXT_GLOBAL) {
// Clear the HTTP authentication cache to avoid leaking state between
// test runs when using the global request context.
test_runner_->GetRequestContext()->ClearHttpAuthCredentials(
new TestCompletionCallback(
base::Bind(&RequestTestHandler::DestroyTest, this)));
return;
}
DestroyTest();
}
void DestroyTest() override {
@@ -2671,6 +2897,16 @@ class RequestTestHandler : public TestHandler {
}
}
// CefRequestHandler::GetAuthCredentials should be called after
// CefURLRequestClient::GetAuthCredentials when the request has an
// associated frame.
if (IsNetworkServiceEnabled() && test_in_browser_ && test_frame_method_ &&
test_runner_->settings_.expect_authentication) {
EXPECT_EQ(1, auth_credentials_ct_);
} else {
EXPECT_EQ(0, auth_credentials_ct_);
}
TestHandler::DestroyTest();
// For non-global contexts OnTestComplete() will be called when the
@@ -2740,26 +2976,6 @@ class RequestTestHandler : public TestHandler {
IMPLEMENT_REFCOUNTING(RequestContextHandler);
};
// Continue the rest once supported schemes have been set.
class SupportedSchemesCompletionCallback : public CefCompletionCallback {
public:
explicit SupportedSchemesCompletionCallback(
const base::Closure& complete_callback)
: complete_callback_(complete_callback) {
EXPECT_FALSE(complete_callback_.is_null());
}
void OnComplete() override {
complete_callback_.Run();
complete_callback_.Reset();
}
private:
base::Closure complete_callback_;
IMPLEMENT_REFCOUNTING(SupportedSchemesCompletionCallback);
};
const RequestTestMode test_mode_;
const ContextTestMode context_mode_;
const bool test_in_browser_;
@@ -2782,6 +2998,7 @@ class RequestTestHandler : public TestHandler {
TrackCallback got_message_;
TrackCallback got_success_;
int auth_credentials_ct_ = 0;
TrackCallback got_on_test_complete_;
IMPLEMENT_REFCOUNTING(RequestTestHandler);
@@ -2873,6 +3090,10 @@ void RegisterURLRequestCustomSchemes(
test_server_backend, test_frame_method) \
REQ_TEST(BrowserPOSTWithProgress##suffix, REQTEST_POST_WITHPROGRESS, \
context_mode, true, test_server_backend, test_frame_method) \
REQ_TEST(BrowserPOSTRedirect##suffix, REQTEST_POST_REDIRECT, context_mode, \
true, test_server_backend, test_frame_method) \
REQ_TEST(BrowserPOSTRedirectToGET##suffix, REQTEST_POST_REDIRECT_TOGET, \
context_mode, true, test_server_backend, test_frame_method) \
REQ_TEST(BrowserHEAD##suffix, REQTEST_HEAD, context_mode, true, \
test_server_backend, test_frame_method) \
REQ_TEST(RendererGET##suffix, REQTEST_GET, context_mode, false, \
@@ -2893,6 +3114,10 @@ void RegisterURLRequestCustomSchemes(
test_server_backend, test_frame_method) \
REQ_TEST(RendererPOSTWithProgress##suffix, REQTEST_POST_WITHPROGRESS, \
context_mode, false, test_server_backend, test_frame_method) \
REQ_TEST(RendererPOSTRedirect##suffix, REQTEST_POST_REDIRECT, context_mode, \
false, test_server_backend, test_frame_method) \
REQ_TEST(RendererPOSTRedirectToGET##suffix, REQTEST_POST_REDIRECT_TOGET, \
context_mode, false, test_server_backend, test_frame_method) \
REQ_TEST(RendererHEAD##suffix, REQTEST_HEAD, context_mode, false, \
test_server_backend, test_frame_method)
@@ -2940,7 +3165,7 @@ REQ_TEST_SET(WithFrame, true)
REQ_TEST_FRAME_SET()
// Cache tests can only be run with the server backend.
// Cache and authentication tests can only be run with the server backend.
#define REQ_TEST_CACHE_SET_EX(suffix, context_mode, test_frame_method) \
REQ_TEST(BrowserGETCacheWithControl##suffix, REQTEST_CACHE_WITH_CONTROL, \
context_mode, true, true, test_frame_method) \
@@ -2972,6 +3197,8 @@ REQ_TEST_FRAME_SET()
REQ_TEST(RendererGETCacheWithoutControl##suffix, \
REQTEST_CACHE_WITHOUT_CONTROL, context_mode, false, true, \
test_frame_method) \
REQ_TEST(BrowserGETAuth##suffix, REQTEST_GET_AUTH, context_mode, true, true, \
test_frame_method) \
REQ_TEST(RendererGETCacheSkipFlag##suffix, REQTEST_CACHE_SKIP_FLAG, \
context_mode, false, true, test_frame_method) \
REQ_TEST(RendererGETCacheSkipHeader##suffix, REQTEST_CACHE_SKIP_HEADER, \

View File

@@ -36,7 +36,8 @@ def RunAction(dir, command):
command[0] = sys.executable
try:
gclient_utils.CheckCallAndFilterAndHeader(command, cwd=dir, always=True)
gclient_utils.CheckCallAndFilter(
command, cwd=dir, always_show_header=True, print_stdout=True)
except gclient_utils.Error, e:
# Use a discrete exit status code of 2 to indicate that a hook action
# failed. Users of this script may wish to treat hook action failures

View File

@@ -440,13 +440,17 @@ def GetConfigArgsSandbox(platform, args, is_debug, cpu):
'use_allocator_shim': False,
# Avoid /LTCG linker warnings and generate smaller lib files.
'is_official_build': False
'is_official_build': False,
}
if is_debug:
# Enable iterator debugging (_ITERATOR_DEBUG_LEVEL=2).
add_args['enable_iterator_debugging'] = True
if platform == 'windows':
# Avoid Debug build linker errors caused by custom libc++.
add_args['use_custom_libcxx'] = False
result = MergeDicts(args, add_args, {
'is_debug': is_debug,
'target_cpu': cpu,