Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Unified Diff: extensions/renderer/api_event_handler.cc

Issue 2722463006: [Extensions Bindings] Notify of event unregistration on invalidation (Closed)
Patch Set: Rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « extensions/renderer/api_event_handler.h ('k') | extensions/renderer/api_event_handler_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/api_event_handler.cc
diff --git a/extensions/renderer/api_event_handler.cc b/extensions/renderer/api_event_handler.cc
index d05e9e48c40ad0275f216647b920dc166eb5f1f4..794b19436638ab4200778061ad77bc629fbbeed5 100644
--- a/extensions/renderer/api_event_handler.cc
+++ b/extensions/renderer/api_event_handler.cc
@@ -28,18 +28,10 @@ const char kExtensionAPIEventPerContextKey[] = "extension_api_events";
struct APIEventPerContextData : public base::SupportsUserData::Data {
APIEventPerContextData(v8::Isolate* isolate) : isolate(isolate) {}
~APIEventPerContextData() override {
- v8::HandleScope scope(isolate);
- // We explicitly clear the event data map here to remove all references to
- // v8 objects. This helps us avoid cycles in v8 where an event listener
- // could hold a reference to the event, which in turn holds the reference
- // to the listener.
- for (const auto& pair : emitters) {
- EventEmitter* emitter = nullptr;
- gin::Converter<EventEmitter*>::FromV8(
- isolate, pair.second.Get(isolate), &emitter);
- CHECK(emitter);
- emitter->listeners()->clear();
- }
+ DCHECK(emitters.empty())
+ << "|emitters| should have been cleared by InvalidateContext()";
+ DCHECK(massagers.empty())
+ << "|massagers| should have been cleared by InvalidateContext()";
}
// The associated v8::Isolate. Since this object is cleaned up at context
@@ -198,6 +190,39 @@ void APIEventHandler::RegisterArgumentMassager(
data->massagers[event_name].Reset(context->GetIsolate(), massager);
}
+void APIEventHandler::InvalidateContext(v8::Local<v8::Context> context) {
+ gin::PerContextData* per_context_data = gin::PerContextData::From(context);
+ DCHECK(per_context_data);
+ APIEventPerContextData* data = static_cast<APIEventPerContextData*>(
+ per_context_data->GetUserData(kExtensionAPIEventPerContextKey));
+ if (!data)
+ return;
+
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
+ // This loop *shouldn't* allow any self-modification (i.e., no listeners
+ // should be added or removed as a result of the iteration). If that changes,
+ // we'll need to cache the listeners elsewhere before iterating.
+ for (const auto& pair : data->emitters) {
+ EventEmitter* emitter = nullptr;
+ gin::Converter<EventEmitter*>::FromV8(isolate, pair.second.Get(isolate),
+ &emitter);
+ CHECK(emitter);
+ emitter->Invalidate();
+ // When the context is shut down, all listeners are removed.
+ listeners_changed_.Run(
+ pair.first, binding::EventListenersChanged::NO_LISTENERS, context);
+ }
+
+ data->emitters.clear();
+ data->massagers.clear();
+
+ // InvalidateContext() is called shortly (and, theoretically, synchronously)
+ // before the PerContextData is deleted. We have a check that guarantees that
+ // no new EventEmitters are created after the PerContextData is deleted, so
+ // no new emitters should be created after this point.
+}
+
size_t APIEventHandler::GetNumEventListenersForTesting(
const std::string& event_name,
v8::Local<v8::Context> context) {
« no previous file with comments | « extensions/renderer/api_event_handler.h ('k') | extensions/renderer/api_event_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698