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

Side by Side Diff: extensions/renderer/event_emitter.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/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 (!valid_)
jbroman 2017/03/01 17:49:47 This won't catch such objects which don't are crea
Devlin 2017/03/01 19:03:50 Yeah, I still don't have a complete grasp of all t
jbroman 2017/03/01 19:26:34 Well, that's slightly later than WillReleaseScript
Devlin 2017/03/02 17:26:32 Done. Added comments in InvalidateContext() and a
62 return;
63
56 v8::Local<v8::Function> listener; 64 v8::Local<v8::Function> listener;
57 // TODO(devlin): For some reason, we don't throw an error when someone calls 65 // 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 66 // add/removeListener with no argument. We probably should. For now, keep
59 // the status quo, but we should revisit this. 67 // the status quo, but we should revisit this.
60 if (!arguments->GetNext(&listener)) 68 if (!arguments->GetNext(&listener))
61 return; 69 return;
62 70
63 v8::Local<v8::Object> holder; 71 v8::Local<v8::Object> holder;
64 CHECK(arguments->GetHolder(&holder)); 72 CHECK(arguments->GetHolder(&holder));
65 CHECK(!holder.IsEmpty()); 73 CHECK(!holder.IsEmpty());
66 v8::Local<v8::Context> context = holder->CreationContext(); 74 v8::Local<v8::Context> context = holder->CreationContext();
67 if (!gin::PerContextData::From(context)) 75 if (!gin::PerContextData::From(context))
68 return; 76 return;
69 77
70 if (!HasListener(listener)) { 78 if (!HasListener(listener)) {
71 listeners_.push_back( 79 listeners_.push_back(
72 v8::Global<v8::Function>(arguments->isolate(), listener)); 80 v8::Global<v8::Function>(arguments->isolate(), listener));
73 if (listeners_.size() == 1) { 81 if (listeners_.size() == 1) {
74 listeners_changed_.Run(binding::EventListenersChanged::HAS_LISTENERS, 82 listeners_changed_.Run(binding::EventListenersChanged::HAS_LISTENERS,
75 context); 83 context);
76 } 84 }
77 } 85 }
78 } 86 }
79 87
80 void EventEmitter::RemoveListener(gin::Arguments* arguments) { 88 void EventEmitter::RemoveListener(gin::Arguments* arguments) {
89 if (!valid_)
jbroman 2017/03/01 17:49:47 Isn't |listeners_| empty in this case anyhow?
Devlin 2017/03/01 19:03:50 Yep, but this seemed more obvious to readers. If
90 return;
91
81 v8::Local<v8::Function> listener; 92 v8::Local<v8::Function> listener;
82 // See comment in AddListener(). 93 // See comment in AddListener().
83 if (!arguments->GetNext(&listener)) 94 if (!arguments->GetNext(&listener))
84 return; 95 return;
85 96
86 auto iter = std::find(listeners_.begin(), listeners_.end(), listener); 97 auto iter = std::find(listeners_.begin(), listeners_.end(), listener);
87 if (iter != listeners_.end()) { 98 if (iter != listeners_.end()) {
88 listeners_.erase(iter); 99 listeners_.erase(iter);
89 if (listeners_.empty()) { 100 if (listeners_.empty()) {
90 v8::Local<v8::Object> holder; 101 v8::Local<v8::Object> holder;
91 CHECK(arguments->GetHolder(&holder)); 102 CHECK(arguments->GetHolder(&holder));
92 CHECK(!holder.IsEmpty()); 103 CHECK(!holder.IsEmpty());
93 v8::Local<v8::Context> context = holder->CreationContext(); 104 v8::Local<v8::Context> context = holder->CreationContext();
94 listeners_changed_.Run(binding::EventListenersChanged::NO_LISTENERS, 105 listeners_changed_.Run(binding::EventListenersChanged::NO_LISTENERS,
95 context); 106 context);
96 } 107 }
97 } 108 }
98 } 109 }
99 110
100 bool EventEmitter::HasListener(v8::Local<v8::Function> listener) { 111 bool EventEmitter::HasListener(v8::Local<v8::Function> listener) {
101 return std::find(listeners_.begin(), listeners_.end(), listener) != 112 return std::find(listeners_.begin(), listeners_.end(), listener) !=
102 listeners_.end(); 113 listeners_.end();
103 } 114 }
104 115
105 bool EventEmitter::HasListeners() { 116 bool EventEmitter::HasListeners() {
106 return !listeners_.empty(); 117 return !listeners_.empty();
107 } 118 }
108 119
109 void EventEmitter::Dispatch(gin::Arguments* arguments) { 120 void EventEmitter::Dispatch(gin::Arguments* arguments) {
121 DCHECK(valid_);
jbroman 2017/03/01 19:26:34 Should this be a DCHECK or an early return? Script
Devlin 2017/03/02 17:26:32 Oh, right, we had to expose this. Forgot about th
122
110 if (listeners_.empty()) 123 if (listeners_.empty())
111 return; 124 return;
112 v8::HandleScope handle_scope(arguments->isolate()); 125 v8::HandleScope handle_scope(arguments->isolate());
113 v8::Local<v8::Context> context = 126 v8::Local<v8::Context> context =
114 arguments->isolate()->GetCurrentContext(); 127 arguments->isolate()->GetCurrentContext();
115 std::vector<v8::Local<v8::Value>> v8_args; 128 std::vector<v8::Local<v8::Value>> v8_args;
116 if (arguments->Length() > 0) { 129 if (arguments->Length() > 0) {
117 // Converting to v8::Values should never fail. 130 // Converting to v8::Values should never fail.
118 CHECK(arguments->GetRemaining(&v8_args)); 131 CHECK(arguments->GetRemaining(&v8_args));
119 } 132 }
120 Fire(context, &v8_args); 133 Fire(context, &v8_args);
121 } 134 }
122 135
123 } // namespace extensions 136 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698