12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// TODO(dcarney): Remove this when UnsafePersistent is removed. 67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/renderer/extensions/object_backed_native_handler.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/linked_ptr.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/renderer/extensions/chrome_v8_context.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/renderer/extensions/console.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/renderer/extensions/module_system.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "v8/include/v8.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Key for the base::Bound routed function. 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* kHandlerFunction = "handler_function"; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ObjectBackedNativeHandler::ObjectBackedNativeHandler( 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChromeV8Context* context) 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : context_(context), 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) object_template_(v8::ObjectTemplate::New()) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ObjectBackedNativeHandler::~ObjectBackedNativeHandler() { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Invalidate(); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)v8::Handle<v8::Object> ObjectBackedNativeHandler::NewInstance() { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return object_template_->NewInstance(); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ObjectBackedNativeHandler::Router( 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const v8::FunctionCallbackInfo<v8::Value>& args) { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::HandleScope handle_scope; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::Object> data = args.Data().As<v8::Object>(); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::Value> handler_function_value = 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data->Get(v8::String::New(kHandlerFunction)); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See comment in header file for why we do this. 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (handler_function_value.IsEmpty() || 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler_function_value->IsUndefined()) { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) console::Error(v8::Context::GetCalling(), 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Extension view no longer exists"); 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(handler_function_value->IsExternal()); 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static_cast<HandlerFunction*>( 557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) handler_function_value.As<v8::External>()->Value())->Run(args); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ObjectBackedNativeHandler::RouteFunction( 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& name, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HandlerFunction& handler_function) { 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Isolate* isolate = v8::Isolate::GetCurrent(); 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::HandleScope handle_scope(isolate); 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(context_->v8_context()); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Persistent<v8::Object> data(isolate, v8::Object::New()); 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Local<v8::Object> local_data = v8::Local<v8::Object>::New(isolate, data); 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) local_data->Set(v8::String::New(kHandlerFunction), 687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::External::New(new HandlerFunction(handler_function))); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::FunctionTemplate> function_template = 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::FunctionTemplate::New(Router, local_data); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) object_template_->Set(name.c_str(), function_template); 727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) router_data_.push_back(UnsafePersistent<v8::Object>(&data)); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ObjectBackedNativeHandler::Invalidate() { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_valid()) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Isolate* isolate = v8::Isolate::GetCurrent(); 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::HandleScope handle_scope(isolate); 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(context_->v8_context()); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (RouterData::iterator it = router_data_.begin(); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != router_data_.end(); ++it) { 847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Handle<v8::Object> data = it->newLocal(isolate); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::Value> handler_function_value = 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data->Get(v8::String::New(kHandlerFunction)); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!handler_function_value.IsEmpty()); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete static_cast<HandlerFunction*>( 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler_function_value.As<v8::External>()->Value()); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data->Delete(v8::String::New(kHandlerFunction)); 917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) it->dispose(); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) object_template_.reset(); 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_ = NULL; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NativeHandler::Invalidate(); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} // namespace extensions 99