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

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: rebase 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 // A map of event names to the number of contexts listening to that event.
43 // We notify the browser about event listeners when we transition between 0
44 // and 1.
45 typedef std::map<std::string, int> EventListenerCounts;
46
47 // A map of extension IDs to listener counts for that extension.
48 base::LazyInstance<std::map<std::string, EventListenerCounts> >
49 g_listener_counts = LAZY_INSTANCE_INITIALIZER;
50
51 // TODO(koz): Merge this into EventBindings.
42 class ExtensionImpl : public ChromeV8Extension { 52 class ExtensionImpl : public ChromeV8Extension {
43 public: 53 public:
54
44 explicit ExtensionImpl(ExtensionDispatcher* dispatcher) 55 explicit ExtensionImpl(ExtensionDispatcher* dispatcher)
45 : ChromeV8Extension("extensions/event.js", 56 : ChromeV8Extension(dispatcher) {
46 IDR_EVENT_BINDINGS_JS, 57 RouteStaticFunction("AttachEvent", &AttachEvent);
47 dispatcher) { 58 RouteStaticFunction("DetachEvent", &DetachEvent);
48 } 59 }
49 ~ExtensionImpl() {} 60 ~ExtensionImpl() {}
50 61
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. 62 // Attach an event name to an object.
62 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) { 63 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) {
63 DCHECK(args.Length() == 1); 64 DCHECK(args.Length() == 1);
64 // TODO(erikkay) should enforce that event name is a string in the bindings 65 // TODO(erikkay) should enforce that event name is a string in the bindings
65 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 66 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
66 67
67 if (args[0]->IsString()) { 68 if (args[0]->IsString()) {
68 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 69 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
69 const ChromeV8ContextSet& context_set = 70 const ChromeV8ContextSet& context_set =
70 self->extension_dispatcher()->v8_context_set(); 71 self->extension_dispatcher()->v8_context_set();
71 ChromeV8Context* context = context_set.GetCurrent(); 72 ChromeV8Context* context = context_set.GetCurrent();
72 CHECK(context); 73 CHECK(context);
73 std::string event_name(*v8::String::AsciiValue(args[0])); 74 std::string event_name(*v8::String::AsciiValue(args[0]));
74 75
75 if (!self->CheckCurrentContextAccessToExtensionAPI(event_name)) 76 if (!self->CheckCurrentContextAccessToExtensionAPI(event_name))
76 return v8::Undefined(); 77 return v8::Undefined();
77 78
78 EventListenerCounts& listener_counts = 79 EventListenerCounts& listener_counts =
79 self->listener_counts_[context->extension_id()]; 80 g_listener_counts.Get()[context->extension_id()];
80 if (++listener_counts[event_name] == 1) { 81 if (++listener_counts[event_name] == 1) {
81 content::RenderThread::Get()->Send( 82 content::RenderThread::Get()->Send(
82 new ExtensionHostMsg_AddListener(context->extension_id(), 83 new ExtensionHostMsg_AddListener(context->extension_id(),
83 event_name)); 84 event_name));
84 } 85 }
85 86
86 // This is called the first time the page has added a listener. Since 87 // 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 88 // the background page is the only lazy page, we know this is the first
88 // time this listener has been registered. 89 // time this listener has been registered.
89 if (self->IsLazyBackgroundPage(context->extension_id())) { 90 if (self->IsLazyBackgroundPage(context->extension_id())) {
(...skipping 13 matching lines...) Expand all
103 104
104 if (args[0]->IsString() && args[1]->IsBoolean()) { 105 if (args[0]->IsString() && args[1]->IsBoolean()) {
105 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 106 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
106 const ChromeV8ContextSet& context_set = 107 const ChromeV8ContextSet& context_set =
107 self->extension_dispatcher()->v8_context_set(); 108 self->extension_dispatcher()->v8_context_set();
108 ChromeV8Context* context = context_set.GetCurrent(); 109 ChromeV8Context* context = context_set.GetCurrent();
109 if (!context) 110 if (!context)
110 return v8::Undefined(); 111 return v8::Undefined();
111 112
112 EventListenerCounts& listener_counts = 113 EventListenerCounts& listener_counts =
113 self->listener_counts_[context->extension_id()]; 114 g_listener_counts.Get()[context->extension_id()];
114 std::string event_name(*v8::String::AsciiValue(args[0])); 115 std::string event_name(*v8::String::AsciiValue(args[0]));
115 bool is_manual = args[1]->BooleanValue(); 116 bool is_manual = args[1]->BooleanValue();
116 117
117 if (--listener_counts[event_name] == 0) { 118 if (--listener_counts[event_name] == 0) {
118 content::RenderThread::Get()->Send( 119 content::RenderThread::Get()->Send(
119 new ExtensionHostMsg_RemoveListener(context->extension_id(), 120 new ExtensionHostMsg_RemoveListener(context->extension_id(),
120 event_name)); 121 event_name));
121 } 122 }
122 123
123 // DetachEvent is called when the last listener for the context is 124 // DetachEvent is called when the last listener for the context is
124 // removed. If the context is the background page, and it removes the 125 // 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 126 // last listener manually, then we assume that it is no longer interested
126 // in being awakened for this event. 127 // in being awakened for this event.
127 if (is_manual && self->IsLazyBackgroundPage(context->extension_id())) { 128 if (is_manual && self->IsLazyBackgroundPage(context->extension_id())) {
128 content::RenderThread::Get()->Send( 129 content::RenderThread::Get()->Send(
129 new ExtensionHostMsg_RemoveLazyListener(context->extension_id(), 130 new ExtensionHostMsg_RemoveLazyListener(context->extension_id(),
130 event_name)); 131 event_name));
131 } 132 }
132 } 133 }
133 134
134 return v8::Undefined(); 135 return v8::Undefined();
135 } 136 }
136 137
137 private: 138 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 139
143 bool IsLazyBackgroundPage(const std::string& extension_id) { 140 bool IsLazyBackgroundPage(const std::string& extension_id) {
144 content::RenderView* render_view = GetCurrentRenderView(); 141 content::RenderView* render_view = GetCurrentRenderView();
145 if (!render_view) 142 if (!render_view)
146 return false; 143 return false;
147 144
148 ExtensionHelper* helper = ExtensionHelper::Get(render_view); 145 ExtensionHelper* helper = ExtensionHelper::Get(render_view);
149 const ::Extension* extension = 146 const ::Extension* extension =
150 extension_dispatcher()->extensions()->GetByID(extension_id); 147 extension_dispatcher()->extensions()->GetByID(extension_id);
151 return (extension && !extension->background_page_persists() && 148 return (extension && !extension->background_page_persists() &&
152 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); 149 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
153 } 150 }
154
155 // A map of extension IDs to listener counts for that extension.
156 std::map<std::string, EventListenerCounts> listener_counts_;
157 }; 151 };
158 152
159 } // namespace 153 } // namespace
160 154
161 v8::Extension* EventBindings::Get(ExtensionDispatcher* dispatcher) { 155 ChromeV8Extension* EventBindings::Get(ExtensionDispatcher* dispatcher) {
162 static v8::Extension* extension = new ExtensionImpl(dispatcher); 156 return new ExtensionImpl(dispatcher);
163 return extension;
164 } 157 }
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/event_bindings.h ('k') | chrome/renderer/extensions/experimental.socket_custom_bindings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698