Fix issues with request callbacks during browser shutdown (see issue #2622).

The behavior has changed as follows with NetworkService enabled:
- All pending and in-progress requests will now be aborted when the CEF context
  or associated browser is destroyed. The OnResourceLoadComplete callback will
  now also be called in this case for in-progress requests that have a handler.
- The CefResourceHandler::Cancel method will now always be called when resource
  handling is complete, irrespective of whether handling completed successfully.
- Request callbacks that arrive after the OnBeforeClose callback for the
  associated browser (which may happen for in-progress requests that are aborted
  on browser destruction) will now always have a non-nullptr CefBrowser
  parameter.
- Allow empty parameters to CefRequest and CefResponse methods where it makes
  sense (e.g. resetting default response state, or clearing a referrer value).
- Fixed a reference loop that was keeping CefResourceHandler objects from being
  destroyed if they were holding a callback reference (from ProcessRequest,
  ReadResponse, etc.) during CEF context or associated browser destruction.
- Fixed an issue where the main frame was not detached on browser destruction
  which could cause a crash due to RFH use-after-free (see issue #2498).

To test: All unit tests pass as expected.
This commit is contained in:
Marshall Greenblatt
2019-05-31 12:50:12 +03:00
parent fd80e5c653
commit fa5268fa2d
21 changed files with 1458 additions and 369 deletions

View File

@@ -113,15 +113,21 @@ class CefBrowserURLRequest::Context
request_context_impl->GetBrowserContext();
DCHECK(browser_context);
content::RenderFrameHost* rfh = nullptr;
scoped_refptr<net_service::URLLoaderFactoryGetter> loader_factory_getter;
if (frame) {
// The request will be associated with this frame/browser.
rfh = static_cast<CefFrameHostImpl*>(frame.get())->GetRenderFrameHost();
// The request will be associated with this frame/browser if it's valid,
// otherwise the request will be canceled.
content::RenderFrameHost* rfh =
static_cast<CefFrameHostImpl*>(frame.get())->GetRenderFrameHost();
if (rfh) {
loader_factory_getter =
net_service::URLLoaderFactoryGetter::Create(rfh, browser_context);
}
} else {
loader_factory_getter =
net_service::URLLoaderFactoryGetter::Create(nullptr, browser_context);
}
auto loader_factory_getter =
net_service::URLLoaderFactoryGetter::Create(rfh, browser_context);
task_runner->PostTask(
FROM_HERE,
base::BindOnce(
@@ -138,6 +144,12 @@ class CefBrowserURLRequest::Context
if (!url_request_)
return;
if (!loader_factory_getter) {
// Cancel the request immediately.
Cancel();
return;
}
DCHECK_EQ(status_, UR_IO_PENDING);
loader_factory_getter_ = loader_factory_getter;