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_.NewHandle(v8::Isolate::GetCurrent())->NewInstance(); 36 } 37 38 // static 39 void ObjectBackedNativeHandler::Router( 40 const v8::FunctionCallbackInfo<v8::Value>& args) { 41 v8::HandleScope handle_scope(args.GetIsolate()); 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::NewFromUtf8(args.GetIsolate(), 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(args.GetIsolate()->GetCallingContext(), 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( 68 v8::String::NewFromUtf8(isolate, kHandlerFunction), 69 v8::External::New(isolate, new HandlerFunction(handler_function))); 70 v8::Handle<v8::FunctionTemplate> function_template = 71 v8::FunctionTemplate::New(isolate, Router, local_data); 72 object_template_.NewHandle(isolate) 73 ->Set(isolate, name.c_str(), function_template); 74 router_data_.push_back(UnsafePersistent<v8::Object>(&data)); 75 } 76 77 void ObjectBackedNativeHandler::Invalidate() { 78 if (!is_valid()) 79 return; 80 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 81 v8::HandleScope handle_scope(isolate); 82 v8::Context::Scope context_scope(context_->v8_context()); 83 84 for (RouterData::iterator it = router_data_.begin(); 85 it != router_data_.end(); ++it) { 86 v8::Handle<v8::Object> data = it->newLocal(isolate); 87 v8::Handle<v8::Value> handler_function_value = 88 data->Get(v8::String::NewFromUtf8(isolate, kHandlerFunction)); 89 CHECK(!handler_function_value.IsEmpty()); 90 delete static_cast<HandlerFunction*>( 91 handler_function_value.As<v8::External>()->Value()); 92 data->Delete(v8::String::NewFromUtf8(isolate, kHandlerFunction)); 93 it->dispose(); 94 } 95 object_template_.reset(); 96 context_ = NULL; 97 NativeHandler::Invalidate(); 98 } 99 100 } // namespace extensions 101