mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-17 04:30:46 +01:00
Fix KeyedServiceFactory assertion during shutdown (issue #2083)
This commit is contained in:
parent
30451b7ca5
commit
a90b50f1ff
@ -23,6 +23,7 @@
|
|||||||
#include "chrome/common/features.h"
|
#include "chrome/common/features.h"
|
||||||
#include "chrome/common/pref_names.h"
|
#include "chrome/common/pref_names.h"
|
||||||
#include "components/content_settings/core/browser/content_settings_utils.h"
|
#include "components/content_settings/core/browser/content_settings_utils.h"
|
||||||
|
#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
#include "content/public/browser/browser_thread.h"
|
#include "content/public/browser/browser_thread.h"
|
||||||
#include "content/public/browser/plugin_service.h"
|
#include "content/public/browser/plugin_service.h"
|
||||||
@ -48,6 +49,39 @@ using content::WebPluginInfo;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// There's a race condition between deletion of the CefPluginInfoMessageFilter
|
||||||
|
// object on the UI thread and deletion of the PrefService (owned by Profile)
|
||||||
|
// on the UI thread. If the PrefService will be deleted first then
|
||||||
|
// PrefMember::Destroy() must be called from ShutdownOnUIThread() to avoid
|
||||||
|
// heap-use-after-free on CefPluginInfoMessageFilter destruction (due to
|
||||||
|
// ~PrefMember trying to access the already-deleted PrefService).
|
||||||
|
// ShutdownNotifierFactory makes sure that ShutdownOnUIThread() is called in
|
||||||
|
// this case.
|
||||||
|
class ShutdownNotifierFactory
|
||||||
|
: public BrowserContextKeyedServiceShutdownNotifierFactory {
|
||||||
|
public:
|
||||||
|
static ShutdownNotifierFactory* GetInstance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend struct base::DefaultLazyInstanceTraits<ShutdownNotifierFactory>;
|
||||||
|
|
||||||
|
ShutdownNotifierFactory()
|
||||||
|
: BrowserContextKeyedServiceShutdownNotifierFactory(
|
||||||
|
"CefPluginInfoMessageFilter") {
|
||||||
|
}
|
||||||
|
~ShutdownNotifierFactory() override {}
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ShutdownNotifierFactory);
|
||||||
|
};
|
||||||
|
|
||||||
|
base::LazyInstance<ShutdownNotifierFactory>::Leaky
|
||||||
|
g_shutdown_notifier_factory = LAZY_INSTANCE_INITIALIZER;
|
||||||
|
|
||||||
|
// static
|
||||||
|
ShutdownNotifierFactory* ShutdownNotifierFactory::GetInstance() {
|
||||||
|
return g_shutdown_notifier_factory.Pointer();
|
||||||
|
}
|
||||||
|
|
||||||
// For certain sandboxed Pepper plugins, use the JavaScript Content Settings.
|
// For certain sandboxed Pepper plugins, use the JavaScript Content Settings.
|
||||||
bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) {
|
bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) {
|
||||||
if (plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS &&
|
if (plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS &&
|
||||||
@ -161,14 +195,29 @@ CefPluginInfoMessageFilter::Context::Context(
|
|||||||
CefPluginInfoMessageFilter::Context::~Context() {
|
CefPluginInfoMessageFilter::Context::~Context() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefPluginInfoMessageFilter::Context::ShutdownOnUIThread() {
|
||||||
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||||
|
always_authorize_plugins_.Destroy();
|
||||||
|
allow_outdated_plugins_.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
CefPluginInfoMessageFilter::CefPluginInfoMessageFilter(
|
CefPluginInfoMessageFilter::CefPluginInfoMessageFilter(
|
||||||
int render_process_id,
|
int render_process_id,
|
||||||
CefBrowserContext* profile)
|
CefBrowserContext* profile)
|
||||||
: BrowserMessageFilter(ExtensionMsgStart),
|
: BrowserMessageFilter(ExtensionMsgStart),
|
||||||
browser_context_(profile),
|
|
||||||
context_(render_process_id, profile),
|
context_(render_process_id, profile),
|
||||||
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
||||||
weak_ptr_factory_(this) {
|
weak_ptr_factory_(this) {
|
||||||
|
shutdown_notifier_ =
|
||||||
|
ShutdownNotifierFactory::GetInstance()->Get(profile)->Subscribe(
|
||||||
|
base::Bind(&CefPluginInfoMessageFilter::ShutdownOnUIThread,
|
||||||
|
base::Unretained(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefPluginInfoMessageFilter::ShutdownOnUIThread() {
|
||||||
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||||
|
context_.ShutdownOnUIThread();
|
||||||
|
shutdown_notifier_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefPluginInfoMessageFilter::OnMessageReceived(
|
bool CefPluginInfoMessageFilter::OnMessageReceived(
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "chrome/browser/plugins/plugin_metadata.h"
|
#include "chrome/browser/plugins/plugin_metadata.h"
|
||||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||||
#include "components/content_settings/core/common/content_settings.h"
|
#include "components/content_settings/core/common/content_settings.h"
|
||||||
|
#include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
|
||||||
#include "components/prefs/pref_member.h"
|
#include "components/prefs/pref_member.h"
|
||||||
#include "content/public/browser/browser_message_filter.h"
|
#include "content/public/browser/browser_message_filter.h"
|
||||||
#include "extensions/features/features.h"
|
#include "extensions/features/features.h"
|
||||||
@ -50,6 +51,7 @@ class CefPluginInfoMessageFilter : public content::BrowserMessageFilter {
|
|||||||
Context(int render_process_id, CefBrowserContext* profile);
|
Context(int render_process_id, CefBrowserContext* profile);
|
||||||
|
|
||||||
~Context();
|
~Context();
|
||||||
|
void ShutdownOnUIThread();
|
||||||
|
|
||||||
void DecidePluginStatus(
|
void DecidePluginStatus(
|
||||||
const GetPluginInfo_Params& params,
|
const GetPluginInfo_Params& params,
|
||||||
@ -95,6 +97,7 @@ class CefPluginInfoMessageFilter : public content::BrowserMessageFilter {
|
|||||||
content::BrowserThread::UI>;
|
content::BrowserThread::UI>;
|
||||||
friend class base::DeleteHelper<CefPluginInfoMessageFilter>;
|
friend class base::DeleteHelper<CefPluginInfoMessageFilter>;
|
||||||
|
|
||||||
|
void ShutdownOnUIThread();
|
||||||
~CefPluginInfoMessageFilter() override;
|
~CefPluginInfoMessageFilter() override;
|
||||||
|
|
||||||
void OnGetPluginInfo(int render_frame_id,
|
void OnGetPluginInfo(int render_frame_id,
|
||||||
@ -125,12 +128,9 @@ class CefPluginInfoMessageFilter : public content::BrowserMessageFilter {
|
|||||||
std::vector<base::string16>* additional_param_values);
|
std::vector<base::string16>* additional_param_values);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scoped_refptr<CefBrowserContext> browser_context_;
|
|
||||||
|
|
||||||
// Members will be destroyed in reverse order of declaration. Due to Context
|
|
||||||
// depending on the PrefService owned by CefBrowserContext the Context object
|
|
||||||
// must be destroyed before the CefBrowserContext object.
|
|
||||||
Context context_;
|
Context context_;
|
||||||
|
std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
|
||||||
|
shutdown_notifier_;
|
||||||
|
|
||||||
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
|
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
|
||||||
base::WeakPtrFactory<CefPluginInfoMessageFilter> weak_ptr_factory_;
|
base::WeakPtrFactory<CefPluginInfoMessageFilter> weak_ptr_factory_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user