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 3 // found in the LICENSE file. 4 5 // TODO(dcarney): Remove this when UnsafePersistent is removed. 6 #define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR 7 8 #include "chrome/renderer/extensions/object_backed_native_handler.h" 9 10 #include "base/logging.h" 11 #include "base/memory/linked_ptr.h" 12 #include "chrome/renderer/extensions/chrome_v8_context.h" 13 #include "chrome/renderer/extensions/console.h" 14 #include "chrome/renderer/extensions/module_system.h" 15 #include "v8/include/v8.h" 16 17 namespace extensions { 18 19 namespace { 20 // Key for the base::Bound routed function. 21 const char* kHandlerFunction = "handler_function"; 22 } // namespace 23 24 ObjectBackedNativeHandler::ObjectBackedNativeHandler( 25 ChromeV8Context* context) 26 : context_(context), 27 object_template_(v8::ObjectTemplate::New()) { 28 } 29 30 ObjectBackedNativeHandler::~ObjectBackedNativeHandler() { 31 Invalidate(); 32 } 33 34 v8::Handle<v8::Object> ObjectBackedNativeHandler::NewInstance() { 35 return object_template_->NewInstance(); 36 } 37 38 // static 39 void ObjectBackedNativeHandler::Router( 40 const v8::FunctionCallbackInfo<v8::Value>& args) { 41 v8::HandleScope handle_scope; 42 v8::Handle<v8::Object> data = args.Data().As<v8::Object>(); 43 44 v8::Handle<v8::Value> handler_function_value = 45 data->Get(v8::String::New(kHandlerFunction)); 46 // See comment in header file for why we do this. 47 if (handler_function_value.IsEmpty() || 48 handler_function_value->IsUndefined()) { 49 console::Error(v8::Context::GetCalling(), 50 "Extension view no longer exists"); 51 return; 52 } 53 DCHECK(handler_function_value->IsExternal()); 54 static_cast<HandlerFunction*>( 55 handler_function_value.As<v8::External>()->Value())->Run(args); 56 } 57 58 void ObjectBackedNativeHandler::RouteFunction( 59 const std::string& name, 60 const HandlerFunction& handler_function) { 61 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 62 v8::HandleScope handle_scope(isolate); 63 v8::Context::Scope context_scope(context_->v8_context()); 64 65 v8::Persistent<v8::Object> data(isolate, v8::Object::New()); 66 v8::Local<v8::Object> local_data = v8::Local<v8::Object>::New(isolate, data); 67 local_data->Set(v8::String::New(kHandlerFunction), 68 v8::External::New(new HandlerFunction(handler_function))); 69 v8::Handle<v8::FunctionTemplate> function_template = 70 v8::FunctionTemplate::New(Router, local_data); 71 object_template_->Set(name.c_str(), function_template); 72 router_data_.push_back(UnsafePersistent<v8::Object>(&data)); 73 } 74 75 void ObjectBackedNativeHandler::Invalidate() { 76 if (!is_valid()) 77 return; 78 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 79 v8::HandleScope handle_scope(isolate); 80 v8::Context::Scope context_scope(context_->v8_context()); 81 82 for (RouterData::iterator it = router_data_.begin(); 83 it != router_data_.end(); ++it) { 84 v8::Handle<v8::Object> data = it->newLocal(isolate); 85 v8::Handle<v8::Value> handler_function_value = 86 data->Get(v8::String::New(kHandlerFunction)); 87 CHECK(!handler_function_value.IsEmpty()); 88 delete static_cast<HandlerFunction*>( 89 handler_function_value.As<v8::External>()->Value()); 90 data->Delete(v8::String::New(kHandlerFunction)); 91 it->dispose(); 92 } 93 object_template_.reset(); 94 context_ = NULL; 95 NativeHandler::Invalidate(); 96 } 97 98 } // namespace extensions 99