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

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

Issue 7717019: Do not dereference potentially invalid frame pointer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 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
« no previous file with comments | « chrome/renderer/extensions/bindings_utils.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 WebKit::WebString::fromUTF8(file_full_path.c_str()), 182 WebKit::WebString::fromUTF8(file_full_path.c_str()),
183 is_directory); 183 is_directory);
184 #else 184 #else
185 return v8::Undefined(); 185 return v8::Undefined();
186 #endif 186 #endif
187 } 187 }
188 }; 188 };
189 189
190 // Returns true if the extension running in the given |context| has sufficient 190 // Returns true if the extension running in the given |context| has sufficient
191 // permissions to access the data. 191 // permissions to access the data.
192 static bool HasSufficientPermissions(ContextInfo* context, 192 static bool HasSufficientPermissions(RenderView* render_view,
193 const GURL& event_url) { 193 const GURL& event_url) {
194 v8::Context::Scope context_scope(context->context);
195
196 // During unit tests, we might be invoked without a v8 context. In these 194 // During unit tests, we might be invoked without a v8 context. In these
197 // cases, we only allow empty event_urls and short-circuit before retrieving 195 // cases, we only allow empty event_urls and short-circuit before retrieving
198 // the render view from the current context. 196 // the render view from the current context.
199 if (!event_url.is_valid()) 197 if (!event_url.is_valid())
200 return true; 198 return true;
201 199
202 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); 200 WebDocument document = render_view->webview()->mainFrame()->document();
203 if (!renderview)
204 return false;
205
206 WebDocument document = renderview->webview()->mainFrame()->document();
207 return GURL(document.url()).SchemeIs(chrome::kExtensionScheme) && 201 return GURL(document.url()).SchemeIs(chrome::kExtensionScheme) &&
208 document.securityOrigin().canRequest(event_url); 202 document.securityOrigin().canRequest(event_url);
209 } 203 }
210 204
211 } // namespace 205 } // namespace
212 206
213 const char* EventBindings::kName = "chrome/EventBindings"; 207 const char* EventBindings::kName = "chrome/EventBindings";
214 const char* EventBindings::kTestingExtensionId = 208 const char* EventBindings::kTestingExtensionId =
215 "oooooooooooooooooooooooooooooooo"; 209 "oooooooooooooooooooooooooooooooo";
216 210
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 v8::Handle<v8::Context> context, 285 v8::Handle<v8::Context> context,
292 ExtensionDispatcher* extension_dispatcher, 286 ExtensionDispatcher* extension_dispatcher,
293 int isolated_world_id) { 287 int isolated_world_id) {
294 if (!bindings_registered) 288 if (!bindings_registered)
295 return; 289 return;
296 290
297 bool content_script = isolated_world_id != 0; 291 bool content_script = isolated_world_id != 0;
298 ContextList& contexts = GetContexts(); 292 ContextList& contexts = GetContexts();
299 293
300 v8::Persistent<v8::Context> persistent_context; 294 v8::Persistent<v8::Context> persistent_context;
295 v8::Persistent<v8::Context> main_world_context;
301 std::string extension_id; 296 std::string extension_id;
302 297
303 if (content_script) { 298 if (content_script) {
304 // Content script contexts can get GCed before their frame goes away, so 299 // Content script contexts can get GCed before their frame goes away, so
305 // set up a GC callback. 300 // set up a GC callback.
306 persistent_context = v8::Persistent<v8::Context>::New(context); 301 persistent_context = v8::Persistent<v8::Context>::New(context);
307 persistent_context.MakeWeak(NULL, &ContextWeakReferenceCallback); 302 persistent_context.MakeWeak(NULL, &ContextWeakReferenceCallback);
303
304 main_world_context = v8::Persistent<v8::Context>::New(
305 frame->mainWorldScriptContext());
306 main_world_context.MakeWeak(NULL, NULL);
307
308 extension_id = 308 extension_id =
309 extension_dispatcher->user_script_slave()-> 309 extension_dispatcher->user_script_slave()->
310 GetExtensionIdForIsolatedWorld(isolated_world_id); 310 GetExtensionIdForIsolatedWorld(isolated_world_id);
311 } else { 311 } else {
312 // Figure out the frame's URL. If the frame is loading, use its provisional 312 // Figure out the frame's URL. If the frame is loading, use its provisional
313 // URL, since we get this notification before commit. 313 // URL, since we get this notification before commit.
314 WebDataSource* ds = frame->provisionalDataSource(); 314 WebDataSource* ds = frame->provisionalDataSource();
315 if (!ds) 315 if (!ds)
316 ds = frame->dataSource(); 316 ds = frame->dataSource();
317 GURL url = ds->request().url(); 317 GURL url = ds->request().url();
(...skipping 11 matching lines...) Expand all
329 329
330 // For tests, we want the dispatchOnLoad to actually setup our bindings, 330 // For tests, we want the dispatchOnLoad to actually setup our bindings,
331 // so we give a fake extension id; 331 // so we give a fake extension id;
332 extension_id = kTestingExtensionId; 332 extension_id = kTestingExtensionId;
333 } 333 }
334 334
335 persistent_context = v8::Persistent<v8::Context>::New(context); 335 persistent_context = v8::Persistent<v8::Context>::New(context);
336 } 336 }
337 337
338 contexts.push_back(linked_ptr<ContextInfo>( 338 contexts.push_back(linked_ptr<ContextInfo>(
339 new ContextInfo(persistent_context, extension_id, frame))); 339 new ContextInfo(persistent_context, main_world_context, extension_id)));
340 340
341 // Content scripts get initialized in user_script_slave.cc. 341 // Content scripts get initialized in user_script_slave.cc.
342 if (!content_script) { 342 if (!content_script) {
343 v8::HandleScope handle_scope; 343 v8::HandleScope handle_scope;
344 v8::Handle<v8::Value> argv[1]; 344 v8::Handle<v8::Value> argv[1];
345 argv[0] = v8::String::New(extension_id.c_str()); 345 argv[0] = v8::String::New(extension_id.c_str());
346 CallFunctionInContext(context, "dispatchOnLoad", arraysize(argv), argv); 346 CallFunctionInContext(context, "dispatchOnLoad", arraysize(argv), argv);
347 } 347 }
348 } 348 }
349 349
350 // static 350 // static
351 void EventBindings::HandleContextDestroyed(WebFrame* frame) { 351 void EventBindings::HandleContextDestroyed(WebFrame* frame) {
352 if (!bindings_registered) 352 if (!bindings_registered)
353 return; 353 return;
354 354
355 v8::HandleScope handle_scope; 355 v8::HandleScope handle_scope;
356 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); 356 v8::Local<v8::Context> context = frame->mainWorldScriptContext();
357 if (!context.IsEmpty()) { 357
358 ContextList::iterator context_iter = bindings_utils::FindContext(context); 358 if (context.IsEmpty()) {
359 if (context_iter != GetContexts().end()) 359 NOTREACHED();
Aaron Boodman 2011/08/24 02:58:16 According to the code upstream, this should not ha
360 UnregisterContext(context_iter, false); 360 return;
361 } 361 }
362 362
363 // Unload any content script contexts for this frame. Note that the frame 363 ContextList::iterator context_iter = bindings_utils::FindContext(context);
364 // itself might not be registered, but can still be a parent frame. 364 if (context_iter != GetContexts().end())
365 UnregisterContext(context_iter, false);
366
367 // Unload any associated content script contexts. Note that the main world
368 // context itself might not be registered, but can still be associated with a
369 // content script that is.
365 for (ContextList::iterator it = GetContexts().begin(); 370 for (ContextList::iterator it = GetContexts().begin();
366 it != GetContexts().end(); ) { 371 it != GetContexts().end(); ) {
367 if ((*it)->frame == frame) { 372 if ((*it)->main_world_context == context) {
368 UnregisterContext(it, false); 373 UnregisterContext(it, false);
369 // UnregisterContext will remove |it| from the list, but may also 374 // UnregisterContext will remove |it| from the list, but may also
370 // modify the rest of the list as a result of calling into javascript. 375 // modify the rest of the list as a result of calling into javascript.
371 it = GetContexts().begin(); 376 it = GetContexts().begin();
372 } else { 377 } else {
373 ++it; 378 ++it;
374 } 379 }
375 } 380 }
376 } 381 }
377 382
378 // static 383 // static
379 void EventBindings::CallFunction(const std::string& extension_id, 384 void EventBindings::CallFunction(const std::string& extension_id,
380 const std::string& function_name, 385 const std::string& function_name,
381 const ListValue& arguments, 386 const ListValue& arguments,
382 RenderView* render_view, 387 RenderView* render_view,
383 const GURL& event_url) { 388 const GURL& event_url) {
384 v8::HandleScope handle_scope; 389 v8::HandleScope handle_scope;
385 390
386 // We copy the context list, because calling into javascript may modify it 391 // We copy the context list, because calling into javascript may modify it
387 // out from under us. We also guard against deleted contexts by checking if 392 // out from under us. We also guard against deleted contexts by checking if
388 // they have been cleared first. 393 // they have been cleared first.
389 ContextList contexts = GetContexts(); 394 ContextList contexts = GetContexts();
390 395
391 V8ValueConverter converter; 396 V8ValueConverter converter;
392 for (ContextList::iterator it = contexts.begin(); 397 for (ContextList::iterator it = contexts.begin();
393 it != contexts.end(); ++it) { 398 it != contexts.end(); ++it) {
394 if (render_view) { 399 if ((*it)->context.IsEmpty())
395 RenderView* context_render_view = 400 continue;
396 RenderView::FromWebView((*it)->frame->view());
397 if (render_view != context_render_view)
398 continue;
399 }
400 401
401 if (!extension_id.empty() && extension_id != (*it)->extension_id) 402 if (!extension_id.empty() && extension_id != (*it)->extension_id)
402 continue; 403 continue;
403 404
404 if ((*it)->context.IsEmpty()) 405 WebFrame* context_frame = WebFrame::frameForContext((*it)->context);
Aaron Boodman 2011/08/24 02:58:16 It will return NULL if the context is detached fro
406 if (!context_frame || !context_frame->view())
405 continue; 407 continue;
406 408
407 if (!HasSufficientPermissions(it->get(), event_url)) 409 RenderView* context_render_view =
410 RenderView::FromWebView(context_frame->view());
411 if (!context_render_view)
412 continue;
413
414 if (render_view && render_view != context_render_view)
415 continue;
416
417 if (!HasSufficientPermissions(render_view, event_url))
408 continue; 418 continue;
409 419
410 v8::Local<v8::Context> context(*((*it)->context)); 420 v8::Local<v8::Context> context(*((*it)->context));
411 std::vector<v8::Handle<v8::Value> > v8_arguments; 421 std::vector<v8::Handle<v8::Value> > v8_arguments;
412 for (size_t i = 0; i < arguments.GetSize(); ++i) { 422 for (size_t i = 0; i < arguments.GetSize(); ++i) {
413 Value* item = NULL; 423 Value* item = NULL;
414 CHECK(arguments.Get(i, &item)); 424 CHECK(arguments.Get(i, &item));
415 v8_arguments.push_back(converter.ToV8Value(item, context)); 425 v8_arguments.push_back(converter.ToV8Value(item, context));
416 } 426 }
417 427
418 v8::Handle<v8::Value> retval = CallFunctionInContext( 428 v8::Handle<v8::Value> retval = CallFunctionInContext(
419 context, function_name, v8_arguments.size(), &v8_arguments[0]); 429 context, function_name, v8_arguments.size(), &v8_arguments[0]);
420 // In debug, the js will validate the event parameters and return a 430 // In debug, the js will validate the event parameters and return a
421 // string if a validation error has occured. 431 // string if a validation error has occured.
422 // TODO(rafaelw): Consider only doing this check if function_name == 432 // TODO(rafaelw): Consider only doing this check if function_name ==
423 // "Event.dispatchJSON". 433 // "Event.dispatchJSON".
424 #ifndef NDEBUG 434 #ifndef NDEBUG
425 if (!retval.IsEmpty() && !retval->IsUndefined()) { 435 if (!retval.IsEmpty() && !retval->IsUndefined()) {
426 std::string error = *v8::String::AsciiValue(retval); 436 std::string error = *v8::String::AsciiValue(retval);
427 DCHECK(false) << error; 437 DCHECK(false) << error;
428 } 438 }
429 #endif 439 #endif
430 } 440 }
431 } 441 }
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/bindings_utils.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698