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

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

Issue 2886923002: [extension SW]: Support event listener registration and event dispatching. (Closed)
Patch Set: address comments Created 3 years, 6 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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_bindings.h" 5 #include "extensions/renderer/event_bindings.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <map> 9 #include <map>
10 #include <memory> 10 #include <memory>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "components/crx_file/id_util.h" 16 #include "components/crx_file/id_util.h"
17 #include "content/public/child/v8_value_converter.h" 17 #include "content/public/child/v8_value_converter.h"
18 #include "content/public/renderer/render_frame.h" 18 #include "content/public/renderer/render_frame.h"
19 #include "content/public/renderer/render_thread.h" 19 #include "content/public/renderer/render_thread.h"
20 #include "content/public/renderer/render_view.h" 20 #include "content/public/renderer/render_view.h"
21 #include "extensions/common/constants.h"
21 #include "extensions/common/event_filter.h" 22 #include "extensions/common/event_filter.h"
22 #include "extensions/common/extension.h" 23 #include "extensions/common/extension.h"
23 #include "extensions/common/extension_messages.h" 24 #include "extensions/common/extension_messages.h"
24 #include "extensions/common/value_counter.h" 25 #include "extensions/common/value_counter.h"
25 #include "extensions/renderer/extension_frame_helper.h" 26 #include "extensions/renderer/extension_frame_helper.h"
26 #include "extensions/renderer/script_context.h" 27 #include "extensions/renderer/script_context.h"
28 #include "extensions/renderer/service_worker_request_sender.h"
29 #include "extensions/renderer/worker_thread_dispatcher.h"
27 #include "url/gurl.h" 30 #include "url/gurl.h"
28 31
29 namespace extensions { 32 namespace extensions {
30 33
31 namespace { 34 namespace {
32 35
33 // A map of event names to the number of contexts listening to that event. 36 // A map of event names to the number of contexts listening to that event.
34 // We notify the browser about event listeners when we transition between 0 37 // We notify the browser about event listeners when we transition between 0
35 // and 1. 38 // and 1.
36 typedef std::map<std::string, int> EventListenerCounts; 39 typedef std::map<std::string, int> EventListenerCounts;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 196
194 // Record the attachment for this context so that events can be detached when 197 // Record the attachment for this context so that events can be detached when
195 // the context is destroyed. 198 // the context is destroyed.
196 // 199 //
197 // Ideally we'd CHECK that it's not already attached, however that's not 200 // Ideally we'd CHECK that it's not already attached, however that's not
198 // possible because extensions can create and attach events themselves. Very 201 // possible because extensions can create and attach events themselves. Very
199 // silly, but that's the way it is. For an example of this, see 202 // silly, but that's the way it is. For an example of this, see
200 // chrome/test/data/extensions/api_test/events/background.js. 203 // chrome/test/data/extensions/api_test/events/background.js.
201 attached_event_names_.insert(event_name); 204 attached_event_names_.insert(event_name);
202 205
206 const int worker_thread_id = content::WorkerThread::GetCurrentId();
203 const std::string& extension_id = context()->GetExtensionID(); 207 const std::string& extension_id = context()->GetExtensionID();
208 const bool is_service_worker_context =
209 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
210 DCHECK_EQ(is_service_worker_context, worker_thread_id != kNonWorkerThreadId);
211 IPC::Sender* sender =
Devlin 2017/06/02 14:53:08 Maybe make a method GetIPCSender() that does this?
lazyboy 2017/06/02 17:58:59 Done.
212 is_service_worker_context
213 ? static_cast<IPC::Sender*>(WorkerThreadDispatcher::Get())
214 : static_cast<IPC::Sender*>(content::RenderThread::Get());
204 if (IncrementEventListenerCount(context(), event_name) == 1) { 215 if (IncrementEventListenerCount(context(), event_name) == 1) {
205 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddListener( 216 sender->Send(new ExtensionHostMsg_AddListener(
206 extension_id, context()->url(), event_name)); 217 extension_id, context()->url(), event_name, worker_thread_id));
207 } 218 }
208 219
209 // This is called the first time the page has added a listener. Since 220 // This is called the first time the page has added a listener. Since
210 // the background page is the only lazy page, we know this is the first 221 // the background page is the only lazy page, we know this is the first
211 // time this listener has been registered. 222 // time this listener has been registered.
212 if (ExtensionFrameHelper::IsContextForEventPage(context())) { 223 sender->Send(new ExtensionHostMsg_AddListener(extension_id, context()->url(),
213 content::RenderThread::Get()->Send( 224 event_name, worker_thread_id));
214 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); 225
226 bool is_lazy_context =
227 ExtensionFrameHelper::IsContextForEventPage(context()) ||
228 is_service_worker_context;
229 if (is_lazy_context) {
230 sender->Send(new ExtensionHostMsg_AddLazyListener(extension_id, event_name,
231 worker_thread_id));
215 } 232 }
216 } 233 }
217 234
218 void EventBindings::DetachEventHandler( 235 void EventBindings::DetachEventHandler(
219 const v8::FunctionCallbackInfo<v8::Value>& args) { 236 const v8::FunctionCallbackInfo<v8::Value>& args) {
220 CHECK_EQ(2, args.Length()); 237 CHECK_EQ(2, args.Length());
221 CHECK(args[0]->IsString()); 238 CHECK(args[0]->IsString());
222 CHECK(args[1]->IsBoolean()); 239 CHECK(args[1]->IsBoolean());
223 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue()); 240 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue());
224 } 241 }
225 242
226 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) { 243 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) {
227 // See comment in AttachEvent(). 244 // See comment in AttachEvent().
228 attached_event_names_.erase(event_name); 245 attached_event_names_.erase(event_name);
229 246
247 int worker_thread_id = content::WorkerThread::GetCurrentId();
248 const bool is_service_worker_context =
249 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
250 DCHECK_EQ(is_service_worker_context, worker_thread_id != kNonWorkerThreadId);
251
252 IPC::Sender* sender =
253 is_service_worker_context
254 ? static_cast<IPC::Sender*>(WorkerThreadDispatcher::Get())
255 : static_cast<IPC::Sender*>(content::RenderThread::Get());
230 const std::string& extension_id = context()->GetExtensionID(); 256 const std::string& extension_id = context()->GetExtensionID();
231 257
232 if (DecrementEventListenerCount(context(), event_name) == 0) { 258 if (DecrementEventListenerCount(context(), event_name) == 0) {
233 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener( 259 sender->Send(new ExtensionHostMsg_RemoveListener(
234 extension_id, context()->url(), event_name)); 260 extension_id, context()->url(), event_name, worker_thread_id));
235 } 261 }
236 262
237 // DetachEvent is called when the last listener for the context is 263 // DetachEvent is called when the last listener for the context is
238 // removed. If the context is the background page, and it removes the 264 // removed. If the context is the background page or service worker, and it
239 // last listener manually, then we assume that it is no longer interested 265 // removes the last listener manually, then we assume that it is no longer
240 // in being awakened for this event. 266 // interested in being awakened for this event.
241 if (is_manual && ExtensionFrameHelper::IsContextForEventPage(context())) { 267 if (is_manual) {
242 content::RenderThread::Get()->Send( 268 bool is_lazy_context =
243 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name)); 269 ExtensionFrameHelper::IsContextForEventPage(context()) ||
270 is_service_worker_context;
271 if (is_lazy_context) {
272 sender->Send(new ExtensionHostMsg_RemoveLazyListener(
273 extension_id, event_name, worker_thread_id));
274 }
244 } 275 }
245 } 276 }
246 277
247 // MatcherID AttachFilteredEvent(string event_name, object filter) 278 // MatcherID AttachFilteredEvent(string event_name, object filter)
248 // event_name - Name of the event to attach. 279 // event_name - Name of the event to attach.
249 // filter - Which instances of the named event are we interested in. 280 // filter - Which instances of the named event are we interested in.
250 // returns the id assigned to the listener, which will be returned from calls 281 // returns the id assigned to the listener, which will be returned from calls
251 // to MatchAgainstEventFilter where this listener matches. 282 // to MatchAgainstEventFilter where this listener matches.
252 void EventBindings::AttachFilteredEvent( 283 void EventBindings::AttachFilteredEvent(
253 const v8::FunctionCallbackInfo<v8::Value>& args) { 284 const v8::FunctionCallbackInfo<v8::Value>& args) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 // Same for filtered events. 395 // Same for filtered events.
365 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_; 396 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_;
366 for (int matcher_id : attached_matcher_ids_safe) { 397 for (int matcher_id : attached_matcher_ids_safe) {
367 DetachFilteredEvent(matcher_id, false /* is_manual */); 398 DetachFilteredEvent(matcher_id, false /* is_manual */);
368 } 399 }
369 DCHECK(attached_matcher_ids_.empty()) 400 DCHECK(attached_matcher_ids_.empty())
370 << "Filtered events cannot be attached during invalidation"; 401 << "Filtered events cannot be attached during invalidation";
371 } 402 }
372 403
373 } // namespace extensions 404 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698