10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "extensions/renderer/v8_schema_registry.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/renderer/v8_value_converter.h" 100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "extensions/common/extension_api.h" 11a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/renderer/object_backed_native_handler.h" 120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "extensions/renderer/script_context.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::V8ValueConverter; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace { 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class SchemaRegistryNativeHandler : public ObjectBackedNativeHandler { 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SchemaRegistryNativeHandler(V8SchemaRegistry* registry, 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<ScriptContext> context) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : ObjectBackedNativeHandler(context.get()), 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_(context.Pass()), 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) registry_(registry) { 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RouteFunction("GetSchema", 280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&SchemaRegistryNativeHandler::GetSchema, 290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Unretained(this))); 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void GetSchema(const v8::FunctionCallbackInfo<v8::Value>& args) { 347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) args.GetReturnValue().Set( 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registry_->GetSchema(*v8::String::Utf8Value(args[0]))); 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<ScriptContext> context_; 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) V8SchemaRegistry* registry_; 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 440529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochV8SchemaRegistry::V8SchemaRegistry() { 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 470529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochV8SchemaRegistry::~V8SchemaRegistry() { 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<NativeHandler> V8SchemaRegistry::AsNativeHandler() { 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<ScriptContext> context( 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new ScriptContext(GetOrCreateContext(v8::Isolate::GetCurrent()), 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NULL, // no frame 540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NULL, // no extension 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Feature::UNSPECIFIED_CONTEXT, 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NULL, // no effective extension 570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Feature::UNSPECIFIED_CONTEXT)); 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return scoped_ptr<NativeHandler>( 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new SchemaRegistryNativeHandler(this, context.Pass())); 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)v8::Handle<v8::Array> V8SchemaRegistry::GetSchemas( 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::vector<std::string>& apis) { 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Isolate* isolate = v8::Isolate::GetCurrent(); 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::EscapableHandleScope handle_scope(isolate); 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Context::Scope context_scope(GetOrCreateContext(isolate)); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Local<v8::Array> v8_apis(v8::Array::New(isolate, apis.size())); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t api_index = 0; 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (std::vector<std::string>::const_iterator i = apis.begin(); 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != apis.end(); 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8_apis->Set(api_index++, GetSchema(*i)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return handle_scope.Escape(v8_apis); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)v8::Handle<v8::Object> V8SchemaRegistry::GetSchema(const std::string& api) { 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (schema_cache_ != NULL) { 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch v8::Local<v8::Object> cached_schema = schema_cache_->Get(api); 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!cached_schema.IsEmpty()) { 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return cached_schema; 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Slow path: Need to build schema first. 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Isolate* isolate = v8::Isolate::GetCurrent(); 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::EscapableHandleScope handle_scope(isolate); 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Handle<v8::Context> context = GetOrCreateContext(isolate); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Context::Scope context_scope(context); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue* schema = 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAPI::GetSharedInstance()->GetSchema(api); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(schema) << api; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<V8ValueConverter> v8_value_converter(V8ValueConverter::create()); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::Value> value = v8_value_converter->ToV8Value(schema, context); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!value.IsEmpty()); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch v8::Local<v8::Object> v8_schema(v8::Handle<v8::Object>::Cast(value)); 101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch schema_cache_->Set(api, v8_schema); 102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return handle_scope.Escape(v8_schema); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)v8::Handle<v8::Context> V8SchemaRegistry::GetOrCreateContext( 1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) v8::Isolate* isolate) { 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It's ok to create local handles in this function, since this is only called 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // when we have a HandleScope. 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!context_holder_) { 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch context_holder_.reset(new gin::ContextHolder(isolate)); 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch context_holder_->SetContext(v8::Context::New(isolate)); 113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch schema_cache_.reset(new SchemaCache(isolate)); 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return context_holder_->context(); 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return context_holder_->context(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 120