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

Side by Side Diff: extensions/renderer/api_event_handler.cc

Issue 2722463006: [Extensions Bindings] Notify of event unregistration on invalidation (Closed)
Patch Set: nits 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/api_event_handler.h" 5 #include "extensions/renderer/api_event_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <memory> 9 #include <memory>
10 #include <vector> 10 #include <vector>
(...skipping 10 matching lines...) Expand all
21 21
22 namespace extensions { 22 namespace extensions {
23 23
24 namespace { 24 namespace {
25 25
26 const char kExtensionAPIEventPerContextKey[] = "extension_api_events"; 26 const char kExtensionAPIEventPerContextKey[] = "extension_api_events";
27 27
28 struct APIEventPerContextData : public base::SupportsUserData::Data { 28 struct APIEventPerContextData : public base::SupportsUserData::Data {
29 APIEventPerContextData(v8::Isolate* isolate) : isolate(isolate) {} 29 APIEventPerContextData(v8::Isolate* isolate) : isolate(isolate) {}
30 ~APIEventPerContextData() override { 30 ~APIEventPerContextData() override {
31 v8::HandleScope scope(isolate); 31 DCHECK(event_data.empty())
32 // We explicitly clear the event data map here to remove all references to 32 << "|event_data| should have been cleared by InvalidateContext()";
33 // v8 objects. This helps us avoid cycles in v8 where an event listener
34 // could hold a reference to the event, which in turn holds the reference
35 // to the listener.
36 for (const auto& pair : event_data) {
37 EventEmitter* emitter = nullptr;
38 gin::Converter<EventEmitter*>::FromV8(
39 isolate, pair.second.Get(isolate), &emitter);
40 CHECK(emitter);
41 emitter->listeners()->clear();
42 }
43 } 33 }
44 34
45 // The associated v8::Isolate. Since this object is cleaned up at context 35 // The associated v8::Isolate. Since this object is cleaned up at context
46 // destruction, this should always be valid. 36 // destruction, this should always be valid.
47 v8::Isolate* isolate; 37 v8::Isolate* isolate;
48 38
49 // A map from event name -> event emitter. 39 // A map from event name -> event emitter.
50 std::map<std::string, v8::Global<v8::Object>> event_data; 40 std::map<std::string, v8::Global<v8::Object>> event_data;
51 }; 41 };
52 42
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 v8_args.push_back(converter->ToV8Value(arg.get(), context)); 110 v8_args.push_back(converter->ToV8Value(arg.get(), context));
121 111
122 EventEmitter* emitter = nullptr; 112 EventEmitter* emitter = nullptr;
123 gin::Converter<EventEmitter*>::FromV8( 113 gin::Converter<EventEmitter*>::FromV8(
124 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter); 114 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter);
125 CHECK(emitter); 115 CHECK(emitter);
126 116
127 emitter->Fire(context, &v8_args); 117 emitter->Fire(context, &v8_args);
128 } 118 }
129 119
120 void APIEventHandler::InvalidateContext(v8::Local<v8::Context> context) {
121 gin::PerContextData* per_context_data = gin::PerContextData::From(context);
122 DCHECK(per_context_data);
123 APIEventPerContextData* data = static_cast<APIEventPerContextData*>(
124 per_context_data->GetUserData(kExtensionAPIEventPerContextKey));
125 if (!data)
126 return;
127
128 v8::Isolate* isolate = context->GetIsolate();
129 v8::HandleScope scope(isolate);
130 for (const auto& pair : data->event_data) {
131 EventEmitter* emitter = nullptr;
132 gin::Converter<EventEmitter*>::FromV8(isolate, pair.second.Get(isolate),
133 &emitter);
134 CHECK(emitter);
135 emitter->Invalidate();
136 // When the context is shut down, all listeners are removed.
137 listeners_changed_.Run(
138 pair.first, binding::EventListenersChanged::NO_LISTENERS, context);
139 }
140
141 data->event_data.clear();
lazyboy 2017/03/03 22:14:19 FYI: If there's a chance that |data->event_data| c
Devlin 2017/03/06 19:11:06 It shouldn't be possible, but I've added a comment
142
143 // InvalidateContext() is called shortly (and, theoretically, synchronously)
144 // before the PerContextData is deleted. We have a check that guarantees that
145 // no new EventEmitters are created after the PerContextData is deleted, so
146 // no new emitters should be created after this point.
147 }
148
130 size_t APIEventHandler::GetNumEventListenersForTesting( 149 size_t APIEventHandler::GetNumEventListenersForTesting(
131 const std::string& event_name, 150 const std::string& event_name,
132 v8::Local<v8::Context> context) { 151 v8::Local<v8::Context> context) {
133 gin::PerContextData* per_context_data = gin::PerContextData::From(context); 152 gin::PerContextData* per_context_data = gin::PerContextData::From(context);
134 DCHECK(per_context_data); 153 DCHECK(per_context_data);
135 APIEventPerContextData* data = static_cast<APIEventPerContextData*>( 154 APIEventPerContextData* data = static_cast<APIEventPerContextData*>(
136 per_context_data->GetUserData(kExtensionAPIEventPerContextKey)); 155 per_context_data->GetUserData(kExtensionAPIEventPerContextKey));
137 DCHECK(data); 156 DCHECK(data);
138 157
139 auto iter = data->event_data.find(event_name); 158 auto iter = data->event_data.find(event_name);
140 DCHECK(iter != data->event_data.end()); 159 DCHECK(iter != data->event_data.end());
141 EventEmitter* emitter = nullptr; 160 EventEmitter* emitter = nullptr;
142 gin::Converter<EventEmitter*>::FromV8( 161 gin::Converter<EventEmitter*>::FromV8(
143 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter); 162 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter);
144 CHECK(emitter); 163 CHECK(emitter);
145 return emitter->listeners()->size(); 164 return emitter->listeners()->size();
146 } 165 }
147 166
148 } // namespace extensions 167 } // namespace extensions
OLDNEW
« 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