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

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

Issue 9386001: Implement a module system for the extension bindings JS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix compile errors Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/renderer/extensions/event_bindings.h" 5 #include "chrome/renderer/extensions/event_bindings.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 21 matching lines...) Expand all
32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
33 #include "v8/include/v8.h" 33 #include "v8/include/v8.h"
34 34
35 using WebKit::WebFrame; 35 using WebKit::WebFrame;
36 using WebKit::WebSecurityOrigin; 36 using WebKit::WebSecurityOrigin;
37 using WebKit::WebURL; 37 using WebKit::WebURL;
38 using content::RenderThread; 38 using content::RenderThread;
39 39
40 namespace { 40 namespace {
41 41
42 // TODO(koz): Merge this into EventBindings.
42 class ExtensionImpl : public ChromeV8Extension { 43 class ExtensionImpl : public ChromeV8Extension {
43 public: 44 public:
44 explicit ExtensionImpl(ExtensionDispatcher* dispatcher) 45 // A map of event names to the number of contexts listening to that event.
45 : ChromeV8Extension("extensions/event.js", 46 // We notify the browser about event listeners when we transition between 0
46 IDR_EVENT_BINDINGS_JS, 47 // and 1.
47 dispatcher) { 48 typedef std::map<std::string, int> EventListenerCounts;
49
50 ExtensionImpl(ExtensionDispatcher* dispatcher,
51 std::map<std::string, EventListenerCounts>* listener_counts)
52 : ChromeV8Extension(dispatcher),
53 listener_counts_(listener_counts) {
54 RouteStaticFunction("AttachEvent", &AttachEvent);
55 RouteStaticFunction("DetachEvent", &DetachEvent);
48 } 56 }
49 ~ExtensionImpl() {} 57 ~ExtensionImpl() {}
50 58
51 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
52 v8::Handle<v8::String> name) {
53 if (name->Equals(v8::String::New("AttachEvent"))) {
54 return v8::FunctionTemplate::New(AttachEvent, v8::External::New(this));
55 } else if (name->Equals(v8::String::New("DetachEvent"))) {
56 return v8::FunctionTemplate::New(DetachEvent, v8::External::New(this));
57 }
58 return ChromeV8Extension::GetNativeFunction(name);
59 }
60
61 // Attach an event name to an object. 59 // Attach an event name to an object.
62 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) { 60 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) {
63 DCHECK(args.Length() == 1); 61 DCHECK(args.Length() == 1);
64 // TODO(erikkay) should enforce that event name is a string in the bindings 62 // TODO(erikkay) should enforce that event name is a string in the bindings
65 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 63 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
66 64
67 if (args[0]->IsString()) { 65 if (args[0]->IsString()) {
68 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 66 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
69 const ChromeV8ContextSet& context_set = 67 const ChromeV8ContextSet& context_set =
70 self->extension_dispatcher()->v8_context_set(); 68 self->extension_dispatcher()->v8_context_set();
71 ChromeV8Context* context = context_set.GetCurrent(); 69 ChromeV8Context* context = context_set.GetCurrent();
72 CHECK(context); 70 CHECK(context);
73 std::string event_name(*v8::String::AsciiValue(args[0])); 71 std::string event_name(*v8::String::AsciiValue(args[0]));
74 72
75 if (!self->CheckCurrentContextAccessToExtensionAPI(event_name)) 73 if (!self->CheckCurrentContextAccessToExtensionAPI(event_name))
76 return v8::Undefined(); 74 return v8::Undefined();
77 75
78 EventListenerCounts& listener_counts = 76 EventListenerCounts& listener_counts =
79 self->listener_counts_[context->extension_id()]; 77 (*(self->listener_counts_))[context->extension_id()];
80 if (++listener_counts[event_name] == 1) { 78 if (++listener_counts[event_name] == 1) {
81 content::RenderThread::Get()->Send( 79 content::RenderThread::Get()->Send(
82 new ExtensionHostMsg_AddListener(context->extension_id(), 80 new ExtensionHostMsg_AddListener(context->extension_id(),
83 event_name)); 81 event_name));
84 } 82 }
85 83
86 // This is called the first time the page has added a listener. Since 84 // This is called the first time the page has added a listener. Since
87 // the background page is the only lazy page, we know this is the first 85 // the background page is the only lazy page, we know this is the first
88 // time this listener has been registered. 86 // time this listener has been registered.
89 if (self->IsLazyBackgroundPage(context->extension_id())) { 87 if (self->IsLazyBackgroundPage(context->extension_id())) {
(...skipping 13 matching lines...) Expand all
103 101
104 if (args[0]->IsString() && args[1]->IsBoolean()) { 102 if (args[0]->IsString() && args[1]->IsBoolean()) {
105 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 103 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
106 const ChromeV8ContextSet& context_set = 104 const ChromeV8ContextSet& context_set =
107 self->extension_dispatcher()->v8_context_set(); 105 self->extension_dispatcher()->v8_context_set();
108 ChromeV8Context* context = context_set.GetCurrent(); 106 ChromeV8Context* context = context_set.GetCurrent();
109 if (!context) 107 if (!context)
110 return v8::Undefined(); 108 return v8::Undefined();
111 109
112 EventListenerCounts& listener_counts = 110 EventListenerCounts& listener_counts =
113 self->listener_counts_[context->extension_id()]; 111 (*(self->listener_counts_))[context->extension_id()];
114 std::string event_name(*v8::String::AsciiValue(args[0])); 112 std::string event_name(*v8::String::AsciiValue(args[0]));
115 bool is_manual = args[1]->BooleanValue(); 113 bool is_manual = args[1]->BooleanValue();
116 114
117 if (--listener_counts[event_name] == 0) { 115 if (--listener_counts[event_name] == 0) {
118 content::RenderThread::Get()->Send( 116 content::RenderThread::Get()->Send(
119 new ExtensionHostMsg_RemoveListener(context->extension_id(), 117 new ExtensionHostMsg_RemoveListener(context->extension_id(),
120 event_name)); 118 event_name));
121 } 119 }
122 120
123 // DetachEvent is called when the last listener for the context is 121 // DetachEvent is called when the last listener for the context is
124 // removed. If the context is the background page, and it removes the 122 // removed. If the context is the background page, and it removes the
125 // last listener manually, then we assume that it is no longer interested 123 // last listener manually, then we assume that it is no longer interested
126 // in being awakened for this event. 124 // in being awakened for this event.
127 if (is_manual && self->IsLazyBackgroundPage(context->extension_id())) { 125 if (is_manual && self->IsLazyBackgroundPage(context->extension_id())) {
128 content::RenderThread::Get()->Send( 126 content::RenderThread::Get()->Send(
129 new ExtensionHostMsg_RemoveLazyListener(context->extension_id(), 127 new ExtensionHostMsg_RemoveLazyListener(context->extension_id(),
130 event_name)); 128 event_name));
131 } 129 }
132 } 130 }
133 131
134 return v8::Undefined(); 132 return v8::Undefined();
135 } 133 }
136 134
137 private: 135 private:
138 // A map of event names to the number of contexts listening to that event.
139 // We notify the browser about event listeners when we transition between 0
140 // and 1.
141 typedef std::map<std::string, int> EventListenerCounts;
142 136
143 bool IsLazyBackgroundPage(const std::string& extension_id) { 137 bool IsLazyBackgroundPage(const std::string& extension_id) {
144 content::RenderView* render_view = GetCurrentRenderView(); 138 content::RenderView* render_view = GetCurrentRenderView();
145 if (!render_view) 139 if (!render_view)
146 return false; 140 return false;
147 141
148 ExtensionHelper* helper = ExtensionHelper::Get(render_view); 142 ExtensionHelper* helper = ExtensionHelper::Get(render_view);
149 const ::Extension* extension = 143 const ::Extension* extension =
150 extension_dispatcher()->extensions()->GetByID(extension_id); 144 extension_dispatcher()->extensions()->GetByID(extension_id);
151 return (extension && !extension->background_page_persists() && 145 return (extension && !extension->background_page_persists() &&
152 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); 146 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
153 } 147 }
154 148
155 // A map of extension IDs to listener counts for that extension. 149 std::map<std::string, ExtensionImpl::EventListenerCounts>* listener_counts_;
156 std::map<std::string, EventListenerCounts> listener_counts_;
157 }; 150 };
158 151
152 // A map of extension IDs to listener counts for that extension.
153 base::LazyInstance<std::map<std::string, ExtensionImpl::EventListenerCounts> >
154 g_listener_counts = LAZY_INSTANCE_INITIALIZER;
Matt Perry 2012/03/01 23:23:06 If this is going to be a global, why not just have
koz (OOO until 15th September) 2012/03/02 01:13:58 Good point. Done.
155
159 } // namespace 156 } // namespace
160 157
161 v8::Extension* EventBindings::Get(ExtensionDispatcher* dispatcher) { 158 ChromeV8Extension* EventBindings::Get(ExtensionDispatcher* dispatcher) {
162 static v8::Extension* extension = new ExtensionImpl(dispatcher); 159 return new ExtensionImpl(dispatcher, g_listener_counts.Pointer());
163 return extension;
164 } 160 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698