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

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;
204 if (IncrementEventListenerCount(context(), event_name) == 1) { 210 if (IncrementEventListenerCount(context(), event_name) == 1) {
205 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddListener( 211 if (is_service_worker_context) {
Devlin 2017/06/01 04:54:50 This is a bit painful. Can we add an IPCSender* a
lazyboy 2017/06/01 23:33:29 I've reworked the code a bit to remove duplicate I
206 extension_id, context()->url(), event_name)); 212 WorkerThreadDispatcher::Get()->GetRequestSender()->SendIPC(
213 new ExtensionHostMsg_AddListener(extension_id, context()->url(),
214 event_name, worker_thread_id));
215 } else {
216 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddListener(
217 extension_id, context()->url(), event_name, kNonWorkerThreadId));
218 }
207 } 219 }
208 220
209 // This is called the first time the page has added a listener. Since 221 // 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 222 // the background page is the only lazy page, we know this is the first
211 // time this listener has been registered. 223 // time this listener has been registered.
212 if (ExtensionFrameHelper::IsContextForEventPage(context())) { 224 if (ExtensionFrameHelper::IsContextForEventPage(context())) {
213 content::RenderThread::Get()->Send( 225 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddLazyListener(
214 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); 226 extension_id, event_name, worker_thread_id));
227 } else if (is_service_worker_context) {
228 // context()->url() example:
229 // chrome-extension://admhefkdknjikemecnclbacmoefgfbdm/sw.js
230 WorkerThreadDispatcher::Get()->GetRequestSender()->SendIPC(
231 new ExtensionHostMsg_AddLazyListener(extension_id, event_name,
232 worker_thread_id));
215 } 233 }
216 } 234 }
217 235
218 void EventBindings::DetachEventHandler( 236 void EventBindings::DetachEventHandler(
219 const v8::FunctionCallbackInfo<v8::Value>& args) { 237 const v8::FunctionCallbackInfo<v8::Value>& args) {
220 CHECK_EQ(2, args.Length()); 238 CHECK_EQ(2, args.Length());
221 CHECK(args[0]->IsString()); 239 CHECK(args[0]->IsString());
222 CHECK(args[1]->IsBoolean()); 240 CHECK(args[1]->IsBoolean());
223 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue()); 241 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue());
224 } 242 }
225 243
226 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) { 244 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) {
227 // See comment in AttachEvent(). 245 // See comment in AttachEvent().
228 attached_event_names_.erase(event_name); 246 attached_event_names_.erase(event_name);
229 247
248 int worker_thread_id = content::WorkerThread::GetCurrentId();
249 const bool is_service_worker_context =
250 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
230 const std::string& extension_id = context()->GetExtensionID(); 251 const std::string& extension_id = context()->GetExtensionID();
231 252
232 if (DecrementEventListenerCount(context(), event_name) == 0) { 253 if (DecrementEventListenerCount(context(), event_name) == 0) {
233 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener( 254 if (is_service_worker_context) {
234 extension_id, context()->url(), event_name)); 255 WorkerThreadDispatcher::Get()->GetRequestSender()->SendIPC(
256 new ExtensionHostMsg_RemoveListener(extension_id, context()->url(),
257 event_name, worker_thread_id));
258 } else {
259 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener(
260 extension_id, context()->url(), event_name, worker_thread_id));
261 }
235 } 262 }
236 263
237 // DetachEvent is called when the last listener for the context is 264 // DetachEvent is called when the last listener for the context is
238 // removed. If the context is the background page, and it removes the 265 // 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 266 // removes the last listener manually, then we assume that it is no longer
240 // in being awakened for this event. 267 // interested in being awakened for this event.
241 if (is_manual && ExtensionFrameHelper::IsContextForEventPage(context())) { 268 if (is_manual) {
242 content::RenderThread::Get()->Send( 269 if (is_service_worker_context) {
243 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name)); 270 WorkerThreadDispatcher::Get()->GetRequestSender()->SendIPC(
271 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name,
272 worker_thread_id));
273 } else if (ExtensionFrameHelper::IsContextForEventPage(context())) {
274 content::RenderThread::Get()->Send(
275 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name,
276 worker_thread_id));
277 }
244 } 278 }
245 } 279 }
246 280
247 // MatcherID AttachFilteredEvent(string event_name, object filter) 281 // MatcherID AttachFilteredEvent(string event_name, object filter)
248 // event_name - Name of the event to attach. 282 // event_name - Name of the event to attach.
249 // filter - Which instances of the named event are we interested in. 283 // 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 284 // returns the id assigned to the listener, which will be returned from calls
251 // to MatchAgainstEventFilter where this listener matches. 285 // to MatchAgainstEventFilter where this listener matches.
252 void EventBindings::AttachFilteredEvent( 286 void EventBindings::AttachFilteredEvent(
253 const v8::FunctionCallbackInfo<v8::Value>& args) { 287 const v8::FunctionCallbackInfo<v8::Value>& args) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 // Same for filtered events. 398 // Same for filtered events.
365 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_; 399 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_;
366 for (int matcher_id : attached_matcher_ids_safe) { 400 for (int matcher_id : attached_matcher_ids_safe) {
367 DetachFilteredEvent(matcher_id, false /* is_manual */); 401 DetachFilteredEvent(matcher_id, false /* is_manual */);
368 } 402 }
369 DCHECK(attached_matcher_ids_.empty()) 403 DCHECK(attached_matcher_ids_.empty())
370 << "Filtered events cannot be attached during invalidation"; 404 << "Filtered events cannot be attached during invalidation";
371 } 405 }
372 406
373 } // namespace extensions 407 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698