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

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

Issue 2886923002: [extension SW]: Support event listener registration and event dispatching. (Closed)
Patch Set: sync 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
« no previous file with comments | « extensions/renderer/event_bindings.h ('k') | extensions/renderer/service_worker_data.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 IPC::Sender* sender = GetIPCSender();
204 if (IncrementEventListenerCount(context(), event_name) == 1) { 209 if (IncrementEventListenerCount(context(), event_name) == 1) {
205 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddListener( 210 sender->Send(new ExtensionHostMsg_AddListener(
206 extension_id, context()->url(), event_name)); 211 extension_id, context()->url(), event_name, worker_thread_id));
207 } 212 }
208 213
209 // This is called the first time the page has added a listener. Since 214 // 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 215 // the background page is the only lazy page, we know this is the first
211 // time this listener has been registered. 216 // time this listener has been registered.
212 if (ExtensionFrameHelper::IsContextForEventPage(context())) { 217 bool is_lazy_context =
213 content::RenderThread::Get()->Send( 218 ExtensionFrameHelper::IsContextForEventPage(context()) ||
214 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); 219 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
220 if (is_lazy_context) {
221 sender->Send(new ExtensionHostMsg_AddLazyListener(extension_id, event_name,
222 worker_thread_id));
215 } 223 }
216 } 224 }
217 225
218 void EventBindings::DetachEventHandler( 226 void EventBindings::DetachEventHandler(
219 const v8::FunctionCallbackInfo<v8::Value>& args) { 227 const v8::FunctionCallbackInfo<v8::Value>& args) {
220 CHECK_EQ(2, args.Length()); 228 CHECK_EQ(2, args.Length());
221 CHECK(args[0]->IsString()); 229 CHECK(args[0]->IsString());
222 CHECK(args[1]->IsBoolean()); 230 CHECK(args[1]->IsBoolean());
223 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue()); 231 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue());
224 } 232 }
225 233
226 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) { 234 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) {
227 // See comment in AttachEvent(). 235 // See comment in AttachEvent().
228 attached_event_names_.erase(event_name); 236 attached_event_names_.erase(event_name);
229 237
238 int worker_thread_id = content::WorkerThread::GetCurrentId();
239 IPC::Sender* sender = GetIPCSender();
230 const std::string& extension_id = context()->GetExtensionID(); 240 const std::string& extension_id = context()->GetExtensionID();
231 241
232 if (DecrementEventListenerCount(context(), event_name) == 0) { 242 if (DecrementEventListenerCount(context(), event_name) == 0) {
233 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener( 243 sender->Send(new ExtensionHostMsg_RemoveListener(
234 extension_id, context()->url(), event_name)); 244 extension_id, context()->url(), event_name, worker_thread_id));
235 } 245 }
236 246
237 // DetachEvent is called when the last listener for the context is 247 // DetachEvent is called when the last listener for the context is
238 // removed. If the context is the background page, and it removes the 248 // 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 249 // removes the last listener manually, then we assume that it is no longer
240 // in being awakened for this event. 250 // interested in being awakened for this event.
241 if (is_manual && ExtensionFrameHelper::IsContextForEventPage(context())) { 251 if (is_manual) {
242 content::RenderThread::Get()->Send( 252 bool is_lazy_context =
243 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name)); 253 ExtensionFrameHelper::IsContextForEventPage(context()) ||
254 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
255 if (is_lazy_context) {
256 sender->Send(new ExtensionHostMsg_RemoveLazyListener(
257 extension_id, event_name, worker_thread_id));
258 }
244 } 259 }
245 } 260 }
246 261
247 // MatcherID AttachFilteredEvent(string event_name, object filter) 262 // MatcherID AttachFilteredEvent(string event_name, object filter)
248 // event_name - Name of the event to attach. 263 // event_name - Name of the event to attach.
249 // filter - Which instances of the named event are we interested in. 264 // 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 265 // returns the id assigned to the listener, which will be returned from calls
251 // to MatchAgainstEventFilter where this listener matches. 266 // to MatchAgainstEventFilter where this listener matches.
252 void EventBindings::AttachFilteredEvent( 267 void EventBindings::AttachFilteredEvent(
253 const v8::FunctionCallbackInfo<v8::Value>& args) { 268 const v8::FunctionCallbackInfo<v8::Value>& args) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 } 359 }
345 args.GetReturnValue().Set(array); 360 args.GetReturnValue().Set(array);
346 } 361 }
347 362
348 std::unique_ptr<EventMatcher> EventBindings::ParseEventMatcher( 363 std::unique_ptr<EventMatcher> EventBindings::ParseEventMatcher(
349 std::unique_ptr<base::DictionaryValue> filter) { 364 std::unique_ptr<base::DictionaryValue> filter) {
350 return base::MakeUnique<EventMatcher>( 365 return base::MakeUnique<EventMatcher>(
351 std::move(filter), context()->GetRenderFrame()->GetRoutingID()); 366 std::move(filter), context()->GetRenderFrame()->GetRoutingID());
352 } 367 }
353 368
369 IPC::Sender* EventBindings::GetIPCSender() {
370 const bool is_service_worker_context =
371 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
372 DCHECK_EQ(is_service_worker_context,
373 content::WorkerThread::GetCurrentId() != kNonWorkerThreadId);
374 return is_service_worker_context
375 ? static_cast<IPC::Sender*>(WorkerThreadDispatcher::Get())
376 : static_cast<IPC::Sender*>(content::RenderThread::Get());
377 }
378
354 void EventBindings::OnInvalidated() { 379 void EventBindings::OnInvalidated() {
355 // Detach all attached events that weren't attached. Iterate over a copy 380 // Detach all attached events that weren't attached. Iterate over a copy
356 // because it will be mutated. 381 // because it will be mutated.
357 std::set<std::string> attached_event_names_safe = attached_event_names_; 382 std::set<std::string> attached_event_names_safe = attached_event_names_;
358 for (const std::string& event_name : attached_event_names_safe) { 383 for (const std::string& event_name : attached_event_names_safe) {
359 DetachEvent(event_name, false /* is_manual */); 384 DetachEvent(event_name, false /* is_manual */);
360 } 385 }
361 DCHECK(attached_event_names_.empty()) 386 DCHECK(attached_event_names_.empty())
362 << "Events cannot be attached during invalidation"; 387 << "Events cannot be attached during invalidation";
363 388
364 // Same for filtered events. 389 // Same for filtered events.
365 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_; 390 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_;
366 for (int matcher_id : attached_matcher_ids_safe) { 391 for (int matcher_id : attached_matcher_ids_safe) {
367 DetachFilteredEvent(matcher_id, false /* is_manual */); 392 DetachFilteredEvent(matcher_id, false /* is_manual */);
368 } 393 }
369 DCHECK(attached_matcher_ids_.empty()) 394 DCHECK(attached_matcher_ids_.empty())
370 << "Filtered events cannot be attached during invalidation"; 395 << "Filtered events cannot be attached during invalidation";
371 } 396 }
372 397
373 } // namespace extensions 398 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/event_bindings.h ('k') | extensions/renderer/service_worker_data.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698