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

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

Issue 2722463006: [Extensions Bindings] Notify of event unregistration on invalidation (Closed)
Patch Set: . 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>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/supports_user_data.h" 15 #include "base/supports_user_data.h"
16 #include "base/values.h" 16 #include "base/values.h"
17 #include "content/public/child/v8_value_converter.h" 17 #include "content/public/child/v8_value_converter.h"
18 #include "extensions/renderer/event_emitter.h" 18 #include "extensions/renderer/event_emitter.h"
19 #include "gin/handle.h" 19 #include "gin/handle.h"
20 #include "gin/per_context_data.h" 20 #include "gin/per_context_data.h"
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 {
Devlin 2017/03/01 15:14:41 If we wanted, we could maybe also make this DCHECK
jbroman 2017/03/01 17:49:47 Yeah, it's a little messy, but I'd rather not have
Devlin 2017/03/01 19:03:50 Done.
31 v8::HandleScope scope(isolate); 31 v8::HandleScope scope(isolate);
32 // We explicitly clear the event data map here to remove all references to 32 // We explicitly clear the event data map here to remove all references to
33 // v8 objects. This helps us avoid cycles in v8 where an event listener 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 34 // could hold a reference to the event, which in turn holds the reference
35 // to the listener. 35 // to the listener.
36 for (const auto& pair : event_data) { 36 for (const auto& pair : event_data) {
37 EventEmitter* emitter = nullptr; 37 EventEmitter* emitter = nullptr;
38 gin::Converter<EventEmitter*>::FromV8( 38 gin::Converter<EventEmitter*>::FromV8(
39 isolate, pair.second.Get(isolate), &emitter); 39 isolate, pair.second.Get(isolate), &emitter);
40 CHECK(emitter); 40 CHECK(emitter);
41 emitter->listeners()->clear(); 41 emitter->Invalidate();
42 } 42 }
43 } 43 }
44 44
45 // The associated v8::Isolate. Since this object is cleaned up at context 45 // The associated v8::Isolate. Since this object is cleaned up at context
46 // destruction, this should always be valid. 46 // destruction, this should always be valid.
47 v8::Isolate* isolate; 47 v8::Isolate* isolate;
48 48
49 // A map from event name -> event emitter. 49 // A map from event name -> event emitter.
50 std::map<std::string, v8::Global<v8::Object>> event_data; 50 std::map<std::string, v8::Global<v8::Object>> event_data;
51 }; 51 };
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 v8_args.push_back(converter->ToV8Value(arg.get(), context)); 120 v8_args.push_back(converter->ToV8Value(arg.get(), context));
121 121
122 EventEmitter* emitter = nullptr; 122 EventEmitter* emitter = nullptr;
123 gin::Converter<EventEmitter*>::FromV8( 123 gin::Converter<EventEmitter*>::FromV8(
124 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter); 124 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter);
125 CHECK(emitter); 125 CHECK(emitter);
126 126
127 emitter->Fire(context, &v8_args); 127 emitter->Fire(context, &v8_args);
128 } 128 }
129 129
130 void APIEventHandler::InvalidateContext(v8::Local<v8::Context> context) {
131 gin::PerContextData* per_context_data = gin::PerContextData::From(context);
132 DCHECK(per_context_data);
133 APIEventPerContextData* data = static_cast<APIEventPerContextData*>(
134 per_context_data->GetUserData(kExtensionAPIEventPerContextKey));
135 if (!data)
136 return;
137
138 v8::Isolate* isolate = context->GetIsolate();
139 v8::HandleScope scope(isolate);
140 for (const auto& pair : data->event_data) {
141 EventEmitter* emitter = nullptr;
142 gin::Converter<EventEmitter*>::FromV8(isolate, pair.second.Get(isolate),
143 &emitter);
144 CHECK(emitter);
145 emitter->Invalidate();
146 listeners_changed_.Run(
147 pair.first, binding::EventListenersChanged::NO_LISTENERS, context);
148 }
149
150 data->event_data.clear();
151 }
152
130 size_t APIEventHandler::GetNumEventListenersForTesting( 153 size_t APIEventHandler::GetNumEventListenersForTesting(
131 const std::string& event_name, 154 const std::string& event_name,
132 v8::Local<v8::Context> context) { 155 v8::Local<v8::Context> context) {
133 gin::PerContextData* per_context_data = gin::PerContextData::From(context); 156 gin::PerContextData* per_context_data = gin::PerContextData::From(context);
134 DCHECK(per_context_data); 157 DCHECK(per_context_data);
135 APIEventPerContextData* data = static_cast<APIEventPerContextData*>( 158 APIEventPerContextData* data = static_cast<APIEventPerContextData*>(
136 per_context_data->GetUserData(kExtensionAPIEventPerContextKey)); 159 per_context_data->GetUserData(kExtensionAPIEventPerContextKey));
137 DCHECK(data); 160 DCHECK(data);
138 161
139 auto iter = data->event_data.find(event_name); 162 auto iter = data->event_data.find(event_name);
140 DCHECK(iter != data->event_data.end()); 163 DCHECK(iter != data->event_data.end());
141 EventEmitter* emitter = nullptr; 164 EventEmitter* emitter = nullptr;
142 gin::Converter<EventEmitter*>::FromV8( 165 gin::Converter<EventEmitter*>::FromV8(
143 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter); 166 context->GetIsolate(), iter->second.Get(context->GetIsolate()), &emitter);
144 CHECK(emitter); 167 CHECK(emitter);
145 return emitter->listeners()->size(); 168 return emitter->listeners()->size();
146 } 169 }
147 170
148 } // namespace extensions 171 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698