Fix possible use after shutdown of BrowserContext (fixes issue #3193)

This commit is contained in:
Marshall Greenblatt 2022-01-10 16:11:16 -05:00
parent 839fdb211c
commit ff0e5c0348
7 changed files with 72 additions and 40 deletions

View File

@ -213,6 +213,9 @@ void CefBrowserContext::Shutdown() {
// Destroy objects that may hold references to the MediaRouter. // Destroy objects that may hold references to the MediaRouter.
media_router_manager_.reset(); media_router_manager_.reset();
// Invalidate any Getter references to this object.
weak_ptr_factory_.InvalidateWeakPtrs();
} }
void CefBrowserContext::AddCefRequestContext(CefRequestContextImpl* context) { void CefBrowserContext::AddCefRequestContext(CefRequestContextImpl* context) {

View File

@ -16,7 +16,7 @@ CefBrowserContext* GetBrowserContext(const CefBrowserContext::Getter& getter) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
DCHECK(!getter.is_null()); DCHECK(!getter.is_null());
// Will return nullptr if the BrowserContext has been destroyed. // Will return nullptr if the BrowserContext has been shut down.
return getter.Run(); return getter.Run();
} }

View File

@ -17,7 +17,7 @@ CefBrowserContext* GetBrowserContext(const CefBrowserContext::Getter& getter) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
DCHECK(!getter.is_null()); DCHECK(!getter.is_null());
// Will return nullptr if the BrowserContext has been destroyed. // Will return nullptr if the BrowserContext has been shut down.
return getter.Run(); return getter.Run();
} }

View File

@ -22,7 +22,16 @@ namespace cookie_helper {
namespace { namespace {
// Do not keep a reference to the CookieManager returned by this method. // Do not keep a reference to the object returned by this method.
CefBrowserContext* GetBrowserContext(const CefBrowserContext::Getter& getter) {
CEF_REQUIRE_UIT();
DCHECK(!getter.is_null());
// Will return nullptr if the BrowserContext has been shut down.
return getter.Run();
}
// Do not keep a reference to the object returned by this method.
network::mojom::CookieManager* GetCookieManager( network::mojom::CookieManager* GetCookieManager(
content::BrowserContext* browser_context) { content::BrowserContext* browser_context) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
@ -82,13 +91,22 @@ void GetCookieListCallback(const AllowCookieCallback& allow_cookie_callback,
} }
void LoadCookiesOnUIThread( void LoadCookiesOnUIThread(
content::BrowserContext* browser_context, const CefBrowserContext::Getter& browser_context_getter,
const GURL& url, const GURL& url,
const net::CookieOptions& options, const net::CookieOptions& options,
net::CookiePartitionKeyCollection cookie_partition_key_collection, net::CookiePartitionKeyCollection cookie_partition_key_collection,
const AllowCookieCallback& allow_cookie_callback, const AllowCookieCallback& allow_cookie_callback,
DoneCookieCallback done_callback) { DoneCookieCallback done_callback) {
CEF_REQUIRE_UIT(); auto cef_browser_context = GetBrowserContext(browser_context_getter);
auto browser_context =
cef_browser_context ? cef_browser_context->AsBrowserContext() : nullptr;
if (!browser_context) {
GetCookieListCallback(allow_cookie_callback, std::move(done_callback),
net::CookieAccessResultList(),
net::CookieAccessResultList());
return;
}
GetCookieManager(browser_context) GetCookieManager(browser_context)
->GetCookieList( ->GetCookieList(
url, options, cookie_partition_key_collection, url, options, cookie_partition_key_collection,
@ -126,15 +144,23 @@ void SetCanonicalCookieCallback(SaveCookiesProgress* progress,
} }
} }
void SaveCookiesOnUIThread(content::BrowserContext* browser_context, void SaveCookiesOnUIThread(
const GURL& url, const CefBrowserContext::Getter& browser_context_getter,
const net::CookieOptions& options, const GURL& url,
int total_count, const net::CookieOptions& options,
net::CookieList cookies, int total_count,
DoneCookieCallback done_callback) { net::CookieList cookies,
CEF_REQUIRE_UIT(); DoneCookieCallback done_callback) {
DCHECK(!cookies.empty()); DCHECK(!cookies.empty());
auto cef_browser_context = GetBrowserContext(browser_context_getter);
auto browser_context =
cef_browser_context ? cef_browser_context->AsBrowserContext() : nullptr;
if (!browser_context) {
std::move(done_callback).Run(0, net::CookieList());
return;
}
network::mojom::CookieManager* cookie_manager = network::mojom::CookieManager* cookie_manager =
GetCookieManager(browser_context); GetCookieManager(browser_context);
@ -186,7 +212,7 @@ bool IsCookieableScheme(
return url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS(); return url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS();
} }
void LoadCookies(content::BrowserContext* browser_context, void LoadCookies(const CefBrowserContext::Getter& browser_context_getter,
const network::ResourceRequest& request, const network::ResourceRequest& request,
const AllowCookieCallback& allow_cookie_callback, const AllowCookieCallback& allow_cookie_callback,
DoneCookieCallback done_callback) { DoneCookieCallback done_callback) {
@ -201,14 +227,13 @@ void LoadCookies(content::BrowserContext* browser_context,
} }
CEF_POST_TASK( CEF_POST_TASK(
CEF_UIT, CEF_UIT, base::BindOnce(LoadCookiesOnUIThread, browser_context_getter,
base::BindOnce(LoadCookiesOnUIThread, browser_context, request.url, request.url, GetCookieOptions(request),
GetCookieOptions(request), net::CookiePartitionKeyCollection(),
net::CookiePartitionKeyCollection(), allow_cookie_callback, std::move(done_callback)));
allow_cookie_callback, std::move(done_callback)));
} }
void SaveCookies(content::BrowserContext* browser_context, void SaveCookies(const CefBrowserContext::Getter& browser_context_getter,
const network::ResourceRequest& request, const network::ResourceRequest& request,
net::HttpResponseHeaders* headers, net::HttpResponseHeaders* headers,
const AllowCookieCallback& allow_cookie_callback, const AllowCookieCallback& allow_cookie_callback,
@ -256,8 +281,8 @@ void SaveCookies(content::BrowserContext* browser_context,
if (!allowed_cookies.empty()) { if (!allowed_cookies.empty()) {
CEF_POST_TASK( CEF_POST_TASK(
CEF_UIT, CEF_UIT,
base::BindOnce(SaveCookiesOnUIThread, browser_context, request.url, base::BindOnce(SaveCookiesOnUIThread, browser_context_getter,
GetCookieOptions(request), total_count, request.url, GetCookieOptions(request), total_count,
std::move(allowed_cookies), std::move(done_callback))); std::move(allowed_cookies), std::move(done_callback)));
} else { } else {

View File

@ -5,13 +5,11 @@
#ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_ #ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_
#define CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_ #define CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_
#include "libcef/browser/browser_context.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "net/cookies/canonical_cookie.h" #include "net/cookies/canonical_cookie.h"
namespace content {
class BrowserContext;
}
namespace net { namespace net {
class HttpResponseHeaders; class HttpResponseHeaders;
} }
@ -44,7 +42,7 @@ using DoneCookieCallback =
// both retrieved and allowed by |allow_cookie_callback|. The loaded cookies // both retrieved and allowed by |allow_cookie_callback|. The loaded cookies
// will not be set on |request|; that should be done in |done_callback|. Must be // will not be set on |request|; that should be done in |done_callback|. Must be
// called on the IO thread. // called on the IO thread.
void LoadCookies(content::BrowserContext* browser_context, void LoadCookies(const CefBrowserContext::Getter& browser_context_getter,
const network::ResourceRequest& request, const network::ResourceRequest& request,
const AllowCookieCallback& allow_cookie_callback, const AllowCookieCallback& allow_cookie_callback,
DoneCookieCallback done_callback); DoneCookieCallback done_callback);
@ -55,7 +53,7 @@ void LoadCookies(content::BrowserContext* browser_context,
// retrieved, and |allowed_cookies| representing the list of cookies that were // retrieved, and |allowed_cookies| representing the list of cookies that were
// both allowed by |allow_cookie_callback| an successfully saved. Must be called // both allowed by |allow_cookie_callback| an successfully saved. Must be called
// on the IO thread. // on the IO thread.
void SaveCookies(content::BrowserContext* browser_context, void SaveCookies(const CefBrowserContext::Getter& browser_context_getter,
const network::ResourceRequest& request, const network::ResourceRequest& request,
net::HttpResponseHeaders* headers, net::HttpResponseHeaders* headers,
const AllowCookieCallback& allow_cookie_callback, const AllowCookieCallback& allow_cookie_callback,

View File

@ -23,7 +23,7 @@ CefBrowserContext* GetBrowserContext(const CefBrowserContext::Getter& getter) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
DCHECK(!getter.is_null()); DCHECK(!getter.is_null());
// Will return nullptr if the BrowserContext has been destroyed. // Will return nullptr if the BrowserContext has been shut down.
return getter.Run(); return getter.Run();
} }

View File

@ -244,10 +244,9 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
const base::RepeatingClosure& unhandled_request_callback) { const base::RepeatingClosure& unhandled_request_callback) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
browser_context_ = browser_context;
auto profile = Profile::FromBrowserContext(browser_context); auto profile = Profile::FromBrowserContext(browser_context);
auto cef_browser_context = CefBrowserContext::FromProfile(profile); auto cef_browser_context = CefBrowserContext::FromProfile(profile);
browser_context_getter_ = cef_browser_context->getter();
iothread_state_ = cef_browser_context->iothread_state(); iothread_state_ = cef_browser_context->iothread_state();
CHECK(iothread_state_); CHECK(iothread_state_);
cookieable_schemes_ = cef_browser_context->GetCookieableSchemes(); cookieable_schemes_ = cef_browser_context->GetCookieableSchemes();
@ -291,7 +290,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
std::unique_ptr<DestructionObserver> observer) {} std::unique_ptr<DestructionObserver> observer) {}
// Only accessed on the UI thread. // Only accessed on the UI thread.
content::BrowserContext* browser_context_ = nullptr; CefBrowserContext::Getter browser_context_getter_;
bool initialized_ = false; bool initialized_ = false;
@ -410,7 +409,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
static void TryCreateURLLoaderNetworkObserver( static void TryCreateURLLoaderNetworkObserver(
std::unique_ptr<PendingRequest> pending_request, std::unique_ptr<PendingRequest> pending_request,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
content::BrowserContext* browser_context, const CefBrowserContext::Getter& browser_context_getter,
base::WeakPtr<InterceptedRequestHandlerWrapper> self) { base::WeakPtr<InterceptedRequestHandlerWrapper> self) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
@ -428,10 +427,16 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
->CreateURLLoaderNetworkObserver(); ->CreateURLLoaderNetworkObserver();
} }
} else { } else {
url_loader_network_observer = auto cef_browser_context = browser_context_getter.Run();
static_cast<content::StoragePartitionImpl*>( auto browser_context = cef_browser_context
browser_context->GetDefaultStoragePartition()) ? cef_browser_context->AsBrowserContext()
->CreateAuthCertObserverForServiceWorker(); : nullptr;
if (browser_context) {
url_loader_network_observer =
static_cast<content::StoragePartitionImpl*>(
browser_context->GetDefaultStoragePartition())
->CreateAuthCertObserverForServiceWorker();
}
} }
CEF_POST_TASK(CEF_IOT, CEF_POST_TASK(CEF_IOT,
@ -488,7 +493,8 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
std::make_unique<PendingRequest>( std::make_unique<PendingRequest>(
request_id, request, request_was_redirected, request_id, request, request_was_redirected,
std::move(callback), std::move(cancel_callback)), std::move(callback), std::move(cancel_callback)),
init_state_->frame_, init_state_->browser_context_, init_state_->frame_,
init_state_->browser_context_getter_,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
@ -582,7 +588,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
&InterceptedRequestHandlerWrapper::ContinueWithLoadedCookies, &InterceptedRequestHandlerWrapper::ContinueWithLoadedCookies,
weak_ptr_factory_.GetWeakPtr(), request_id, request, weak_ptr_factory_.GetWeakPtr(), request_id, request,
std::move(callback)); std::move(callback));
cookie_helper::LoadCookies(init_state_->browser_context_, *request, cookie_helper::LoadCookies(init_state_->browser_context_getter_, *request,
allow_cookie_callback, allow_cookie_callback,
std::move(done_cookie_callback)); std::move(done_cookie_callback));
} }
@ -960,8 +966,8 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
auto done_cookie_callback = base::BindOnce( auto done_cookie_callback = base::BindOnce(
&InterceptedRequestHandlerWrapper::ContinueWithSavedCookies, &InterceptedRequestHandlerWrapper::ContinueWithSavedCookies,
weak_ptr_factory_.GetWeakPtr(), request_id, std::move(callback)); weak_ptr_factory_.GetWeakPtr(), request_id, std::move(callback));
cookie_helper::SaveCookies(init_state_->browser_context_, *request, headers, cookie_helper::SaveCookies(init_state_->browser_context_getter_, *request,
allow_cookie_callback, headers, allow_cookie_callback,
std::move(done_cookie_callback)); std::move(done_cookie_callback));
} }