OLD | NEW |
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 Loading... |
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 |
OLD | NEW |