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

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

Issue 155707: Changed the extension.connect() API not to broadcast to all tabs. Added a (Closed)
Patch Set: review comments Created 11 years, 5 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 (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/singleton.h" 8 #include "base/singleton.h"
9 #include "chrome/common/render_messages.h" 9 #include "chrome/common/render_messages.h"
10 #include "chrome/common/url_constants.h" 10 #include "chrome/common/url_constants.h"
11 #include "chrome/renderer/extensions/bindings_utils.h" 11 #include "chrome/renderer/extensions/bindings_utils.h"
12 #include "chrome/renderer/extensions/event_bindings.h" 12 #include "chrome/renderer/extensions/event_bindings.h"
13 #include "chrome/renderer/js_only_v8_extensions.h" 13 #include "chrome/renderer/js_only_v8_extensions.h"
14 #include "chrome/renderer/render_thread.h" 14 #include "chrome/renderer/render_thread.h"
15 #include "chrome/renderer/render_view.h" 15 #include "chrome/renderer/render_view.h"
16 #include "grit/renderer_resources.h" 16 #include "grit/renderer_resources.h"
17 #include "webkit/api/public/WebDataSource.h"
18 #include "webkit/api/public/WebURLRequest.h"
17 #include "webkit/glue/webframe.h" 19 #include "webkit/glue/webframe.h"
18 20
19 using bindings_utils::CallFunctionInContext; 21 using bindings_utils::CallFunctionInContext;
20 using bindings_utils::ContextInfo; 22 using bindings_utils::ContextInfo;
21 using bindings_utils::ContextList; 23 using bindings_utils::ContextList;
22 using bindings_utils::GetContexts; 24 using bindings_utils::GetContexts;
23 using bindings_utils::GetStringResource; 25 using bindings_utils::GetStringResource;
24 using bindings_utils::ExtensionBase; 26 using bindings_utils::ExtensionBase;
25 using bindings_utils::GetPendingRequestMap; 27 using bindings_utils::GetPendingRequestMap;
26 using bindings_utils::PendingRequestMap; 28 using bindings_utils::PendingRequestMap;
27 29
28 namespace { 30 namespace {
29 31
30 // Keep a local cache of RenderThread so that we can mock it out for unit tests. 32 // Keep a local cache of RenderThread so that we can mock it out for unit tests.
31 static RenderThreadBase* render_thread = NULL; 33 static RenderThreadBase* render_thread = NULL;
34 static bool in_unit_tests = false;
32 35
33 // Set to true if these bindings are registered. Will be false when extensions 36 // Set to true if these bindings are registered. Will be false when extensions
34 // are disabled. 37 // are disabled.
35 static bool bindings_registered = false; 38 static bool bindings_registered = false;
36 39
37 struct ExtensionData { 40 struct ExtensionData {
38 std::map<std::string, int> listener_count; 41 std::map<std::string, int> listener_count;
39 }; 42 };
40 int EventIncrementListenerCount(const std::string& event_name) { 43 int EventIncrementListenerCount(const std::string& event_name) {
41 ExtensionData *data = Singleton<ExtensionData>::get(); 44 ExtensionData *data = Singleton<ExtensionData>::get();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 const char* EventBindings::kName = "chrome/EventBindings"; 107 const char* EventBindings::kName = "chrome/EventBindings";
105 108
106 v8::Extension* EventBindings::Get() { 109 v8::Extension* EventBindings::Get() {
107 bindings_registered = true; 110 bindings_registered = true;
108 return new ExtensionImpl(); 111 return new ExtensionImpl();
109 } 112 }
110 113
111 // static 114 // static
112 void EventBindings::SetRenderThread(RenderThreadBase* thread) { 115 void EventBindings::SetRenderThread(RenderThreadBase* thread) {
113 render_thread = thread; 116 render_thread = thread;
117 in_unit_tests = true;
114 } 118 }
115 119
116 // static 120 // static
117 RenderThreadBase* EventBindings::GetRenderThread() { 121 RenderThreadBase* EventBindings::GetRenderThread() {
118 return render_thread ? render_thread : RenderThread::current(); 122 return render_thread ? render_thread : RenderThread::current();
119 } 123 }
120 124
121 static void HandleContextDestroyed(ContextList::iterator context_iter, 125 static void HandleContextDestroyed(ContextList::iterator context_iter,
122 bool callUnload) { 126 bool callUnload) {
123 // Notify the bindings that they're going away. 127 // Notify the bindings that they're going away.
(...skipping 19 matching lines...) Expand all
143 it != GetContexts().end(); ) { 147 it != GetContexts().end(); ) {
144 ContextList::iterator current = it++; 148 ContextList::iterator current = it++;
145 if ((*current)->parent_context == (*context_iter)->context) 149 if ((*current)->parent_context == (*context_iter)->context)
146 HandleContextDestroyed(current, callUnload); 150 HandleContextDestroyed(current, callUnload);
147 } 151 }
148 152
149 // Remove it from our registered contexts. 153 // Remove it from our registered contexts.
150 (*context_iter)->context.ClearWeak(); 154 (*context_iter)->context.ClearWeak();
151 (*context_iter)->context.Dispose(); 155 (*context_iter)->context.Dispose();
152 (*context_iter)->context.Clear(); 156 (*context_iter)->context.Clear();
157
158 if (!(*context_iter)->parent_context.IsEmpty()) {
159 (*context_iter)->parent_context.Dispose();
160 (*context_iter)->parent_context.Clear();
161 }
162
153 GetContexts().erase(context_iter); 163 GetContexts().erase(context_iter);
154 } 164 }
155 165
156 static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, 166 static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context,
157 void*) 167 void*) {
158 {
159 for (ContextList::iterator it = GetContexts().begin(); 168 for (ContextList::iterator it = GetContexts().begin();
160 it != GetContexts().end(); ++it) { 169 it != GetContexts().end(); ++it) {
161 if ((*it)->context == context) { 170 if ((*it)->context == context) {
162 HandleContextDestroyed(it, false); 171 HandleContextDestroyed(it, false);
163 return; 172 return;
164 } 173 }
165 } 174 }
166 175
167 NOTREACHED(); 176 NOTREACHED();
168 } 177 }
169 178
170 void EventBindings::HandleContextCreated(WebFrame* frame) { 179 void EventBindings::HandleContextCreated(WebFrame* frame, bool content_script) {
171 if (!bindings_registered) 180 if (!bindings_registered)
172 return; 181 return;
173 182
174 v8::HandleScope handle_scope; 183 v8::HandleScope handle_scope;
175 ContextList& contexts = GetContexts(); 184 ContextList& contexts = GetContexts();
176 v8::Local<v8::Context> frame_context = frame->GetScriptContext(); 185 v8::Local<v8::Context> frame_context = frame->GetScriptContext();
177 v8::Local<v8::Context> context = v8::Context::GetCurrent(); 186 v8::Local<v8::Context> context = v8::Context::GetCurrent();
178 DCHECK(!context.IsEmpty()); 187 DCHECK(!context.IsEmpty());
179 DCHECK(bindings_utils::FindContext(context) == contexts.end()); 188 DCHECK(bindings_utils::FindContext(context) == contexts.end());
180 189
181 GURL url = frame->GetView()->GetMainFrame()->GetURL(); 190 // Figure out the URL for the toplevel frame. If the top frame is loading,
191 // use its provisional URL, since we get this notification before commit.
192 WebFrame* main_frame = frame->GetView()->GetMainFrame();
193 WebKit::WebDataSource* ds = main_frame->GetProvisionalDataSource();
194 if (!ds)
195 ds = main_frame->GetDataSource();
196 GURL url = ds->request().url();
182 std::string extension_id; 197 std::string extension_id;
183 if (url.SchemeIs(chrome::kExtensionScheme)) 198 if (url.SchemeIs(chrome::kExtensionScheme)) {
184 extension_id = url.host(); 199 extension_id = url.host();
200 } else if (!content_script) {
201 // This context is a regular non-extension web page. Ignore it. We only
202 // care about content scripts and extension frames.
203 // (Unless we're in unit tests, in which case we don't care what the URL
204 // is).
205 DCHECK(frame_context == context);
206 if (!in_unit_tests)
207 return;
208 }
185 209
186 v8::Persistent<v8::Context> persistent_context = 210 v8::Persistent<v8::Context> persistent_context =
187 v8::Persistent<v8::Context>::New(context); 211 v8::Persistent<v8::Context>::New(context);
188 v8::Persistent<v8::Context> parent_context; 212 v8::Persistent<v8::Context> parent_context;
189 213
190 if (frame_context != context) { 214 if (content_script) {
191 // The new context doesn't belong to the frame: it's a content script. 215 DCHECK(frame_context != context);
192 DCHECK(bindings_utils::FindContext(frame_context) != contexts.end()); 216
193 parent_context = v8::Persistent<v8::Context>::New(frame_context); 217 parent_context = v8::Persistent<v8::Context>::New(frame_context);
194 // Content script contexts can get GCed before their frame goes away, so 218 // Content script contexts can get GCed before their frame goes away, so
195 // set up a GC callback. 219 // set up a GC callback.
196 persistent_context.MakeWeak(NULL, &ContextWeakReferenceCallback); 220 persistent_context.MakeWeak(NULL, &ContextWeakReferenceCallback);
197 } 221 }
198 222
223 RenderView* render_view = NULL;
224 if (frame->GetView() && frame->GetView()->GetDelegate())
225 render_view = static_cast<RenderView*>(frame->GetView()->GetDelegate());
226
199 contexts.push_back(linked_ptr<ContextInfo>( 227 contexts.push_back(linked_ptr<ContextInfo>(
200 new ContextInfo(persistent_context, extension_id, parent_context))); 228 new ContextInfo(persistent_context, extension_id, parent_context,
229 render_view)));
201 230
202 v8::Handle<v8::Value> argv[1]; 231 v8::Handle<v8::Value> argv[1];
203 argv[0] = v8::String::New(extension_id.c_str()); 232 argv[0] = v8::String::New(extension_id.c_str());
204 CallFunctionInContext(context, "dispatchOnLoad", arraysize(argv), argv); 233 CallFunctionInContext(context, "dispatchOnLoad", arraysize(argv), argv);
205 } 234 }
206 235
207 // static 236 // static
208 void EventBindings::HandleContextDestroyed(WebFrame* frame) { 237 void EventBindings::HandleContextDestroyed(WebFrame* frame) {
209 if (!bindings_registered) 238 if (!bindings_registered)
210 return; 239 return;
211 240
212 v8::HandleScope handle_scope; 241 v8::HandleScope handle_scope;
213 v8::Local<v8::Context> context = frame->GetScriptContext(); 242 v8::Local<v8::Context> context = frame->GetScriptContext();
214 DCHECK(!context.IsEmpty()); 243 DCHECK(!context.IsEmpty());
215 244
216 ContextList::iterator context_iter = bindings_utils::FindContext(context); 245 ContextList::iterator context_iter = bindings_utils::FindContext(context);
217 DCHECK(context_iter != GetContexts().end()); 246 if (context_iter != GetContexts().end())
218 ::HandleContextDestroyed(context_iter, true); 247 ::HandleContextDestroyed(context_iter, true);
219 } 248 }
220 249
221 // static 250 // static
222 void EventBindings::CallFunction(const std::string& function_name, 251 void EventBindings::CallFunction(const std::string& function_name,
223 int argc, v8::Handle<v8::Value>* argv) { 252 int argc, v8::Handle<v8::Value>* argv,
253 RenderView* render_view) {
224 for (ContextList::iterator it = GetContexts().begin(); 254 for (ContextList::iterator it = GetContexts().begin();
225 it != GetContexts().end(); ++it) { 255 it != GetContexts().end(); ++it) {
256 if (render_view && render_view != (*it)->render_view)
257 continue;
226 CallFunctionInContext((*it)->context, function_name, argc, argv); 258 CallFunctionInContext((*it)->context, function_name, argc, argv);
227 } 259 }
228 } 260 }
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/event_bindings.h ('k') | chrome/renderer/extensions/extension_process_bindings.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698