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

Side by Side Diff: extensions/renderer/event_emitter.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 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/event_emitter.h" 5 #include "extensions/renderer/event_emitter.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "gin/object_template_builder.h" 9 #include "gin/object_template_builder.h"
10 #include "gin/per_context_data.h" 10 #include "gin/per_context_data.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 for (const auto& listener : listeners) { 45 for (const auto& listener : listeners) {
46 v8::TryCatch try_catch(context->GetIsolate()); 46 v8::TryCatch try_catch(context->GetIsolate());
47 // SetVerbose() means the error will still get logged, which is what we 47 // SetVerbose() means the error will still get logged, which is what we
48 // want. We don't let it bubble up any further to prevent it from being 48 // want. We don't let it bubble up any further to prevent it from being
49 // surfaced in e.g. JS code that triggered the event. 49 // surfaced in e.g. JS code that triggered the event.
50 try_catch.SetVerbose(true); 50 try_catch.SetVerbose(true);
51 run_js_.Run(listener, context, args->size(), args->data()); 51 run_js_.Run(listener, context, args->size(), args->data());
52 } 52 }
53 } 53 }
54 54
55 void EventEmitter::Invalidate() {
56 valid_ = false;
57 listeners_.clear();
58 }
59
55 void EventEmitter::AddListener(gin::Arguments* arguments) { 60 void EventEmitter::AddListener(gin::Arguments* arguments) {
61 // If script from another context maintains a reference to this object, it's
62 // possible that functions can be called after this object's owning context
63 // is torn down and released by blink. We don't support this behavior, but
64 // we need to make sure nothing crashes, so early out of methods.
65 if (!valid_)
66 return;
67
56 v8::Local<v8::Function> listener; 68 v8::Local<v8::Function> listener;
57 // TODO(devlin): For some reason, we don't throw an error when someone calls 69 // TODO(devlin): For some reason, we don't throw an error when someone calls
58 // add/removeListener with no argument. We probably should. For now, keep 70 // add/removeListener with no argument. We probably should. For now, keep
59 // the status quo, but we should revisit this. 71 // the status quo, but we should revisit this.
60 if (!arguments->GetNext(&listener)) 72 if (!arguments->GetNext(&listener))
61 return; 73 return;
62 74
63 v8::Local<v8::Object> holder; 75 v8::Local<v8::Object> holder;
64 CHECK(arguments->GetHolder(&holder)); 76 CHECK(arguments->GetHolder(&holder));
65 CHECK(!holder.IsEmpty()); 77 CHECK(!holder.IsEmpty());
66 v8::Local<v8::Context> context = holder->CreationContext(); 78 v8::Local<v8::Context> context = holder->CreationContext();
67 if (!gin::PerContextData::From(context)) 79 if (!gin::PerContextData::From(context))
68 return; 80 return;
69 81
70 if (!HasListener(listener)) { 82 if (!HasListener(listener)) {
71 listeners_.push_back( 83 listeners_.push_back(
72 v8::Global<v8::Function>(arguments->isolate(), listener)); 84 v8::Global<v8::Function>(arguments->isolate(), listener));
73 if (listeners_.size() == 1) { 85 if (listeners_.size() == 1) {
74 listeners_changed_.Run(binding::EventListenersChanged::HAS_LISTENERS, 86 listeners_changed_.Run(binding::EventListenersChanged::HAS_LISTENERS,
75 context); 87 context);
76 } 88 }
77 } 89 }
78 } 90 }
79 91
80 void EventEmitter::RemoveListener(gin::Arguments* arguments) { 92 void EventEmitter::RemoveListener(gin::Arguments* arguments) {
93 // See comment in AddListener().
94 if (!valid_)
95 return;
96
81 v8::Local<v8::Function> listener; 97 v8::Local<v8::Function> listener;
82 // See comment in AddListener(). 98 // See comment in AddListener().
83 if (!arguments->GetNext(&listener)) 99 if (!arguments->GetNext(&listener))
84 return; 100 return;
85 101
86 auto iter = std::find(listeners_.begin(), listeners_.end(), listener); 102 auto iter = std::find(listeners_.begin(), listeners_.end(), listener);
87 if (iter != listeners_.end()) { 103 if (iter != listeners_.end()) {
88 listeners_.erase(iter); 104 listeners_.erase(iter);
89 if (listeners_.empty()) { 105 if (listeners_.empty()) {
90 v8::Local<v8::Object> holder; 106 v8::Local<v8::Object> holder;
91 CHECK(arguments->GetHolder(&holder)); 107 CHECK(arguments->GetHolder(&holder));
92 CHECK(!holder.IsEmpty()); 108 CHECK(!holder.IsEmpty());
93 v8::Local<v8::Context> context = holder->CreationContext(); 109 v8::Local<v8::Context> context = holder->CreationContext();
94 listeners_changed_.Run(binding::EventListenersChanged::NO_LISTENERS, 110 listeners_changed_.Run(binding::EventListenersChanged::NO_LISTENERS,
95 context); 111 context);
96 } 112 }
97 } 113 }
98 } 114 }
99 115
100 bool EventEmitter::HasListener(v8::Local<v8::Function> listener) { 116 bool EventEmitter::HasListener(v8::Local<v8::Function> listener) {
101 return std::find(listeners_.begin(), listeners_.end(), listener) != 117 return std::find(listeners_.begin(), listeners_.end(), listener) !=
102 listeners_.end(); 118 listeners_.end();
103 } 119 }
104 120
105 bool EventEmitter::HasListeners() { 121 bool EventEmitter::HasListeners() {
106 return !listeners_.empty(); 122 return !listeners_.empty();
107 } 123 }
108 124
109 void EventEmitter::Dispatch(gin::Arguments* arguments) { 125 void EventEmitter::Dispatch(gin::Arguments* arguments) {
126 if (!valid_)
127 return;
128
110 if (listeners_.empty()) 129 if (listeners_.empty())
111 return; 130 return;
112 v8::HandleScope handle_scope(arguments->isolate()); 131 v8::HandleScope handle_scope(arguments->isolate());
113 v8::Local<v8::Context> context = 132 v8::Local<v8::Context> context =
114 arguments->isolate()->GetCurrentContext(); 133 arguments->isolate()->GetCurrentContext();
115 std::vector<v8::Local<v8::Value>> v8_args; 134 std::vector<v8::Local<v8::Value>> v8_args;
116 if (arguments->Length() > 0) { 135 if (arguments->Length() > 0) {
117 // Converting to v8::Values should never fail. 136 // Converting to v8::Values should never fail.
118 CHECK(arguments->GetRemaining(&v8_args)); 137 CHECK(arguments->GetRemaining(&v8_args));
119 } 138 }
120 Fire(context, &v8_args); 139 Fire(context, &v8_args);
121 } 140 }
122 141
123 } // namespace extensions 142 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/event_emitter.h ('k') | extensions/renderer/native_extension_bindings_system.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698