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

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

Issue 9616055: Make a process-wide cache for the v8::Value representation of extension APIs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 9 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/schema_generated_bindings.h" 5 #include "chrome/renderer/extensions/schema_generated_bindings.h"
6 6
7 #include <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 10
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 public: 71 public:
72 explicit ExtensionImpl(ExtensionDispatcher* extension_dispatcher) 72 explicit ExtensionImpl(ExtensionDispatcher* extension_dispatcher)
73 : ChromeV8Extension(extension_dispatcher) { 73 : ChromeV8Extension(extension_dispatcher) {
74 RouteStaticFunction("GetExtensionAPIDefinition", 74 RouteStaticFunction("GetExtensionAPIDefinition",
75 &GetExtensionAPIDefinition); 75 &GetExtensionAPIDefinition);
76 RouteStaticFunction("GetNextRequestId", &GetNextRequestId); 76 RouteStaticFunction("GetNextRequestId", &GetNextRequestId);
77 RouteStaticFunction("StartRequest", &StartRequest); 77 RouteStaticFunction("StartRequest", &StartRequest);
78 RouteStaticFunction("SetIconCommon", &SetIconCommon); 78 RouteStaticFunction("SetIconCommon", &SetIconCommon);
79 } 79 }
80 80
81 ~ExtensionImpl() {
82 // TODO(aa): It seems that v8 never deletes us, so this doesn't get called.
83 // Leaving this in here in case v8's implementation ever changes.
84 for (CachedSchemaMap::iterator it = schemas_.begin(); it != schemas_.end();
85 ++it) {
86 if (!it->second.IsEmpty())
87 it->second.Dispose();
88 }
89 }
90
91 private: 81 private:
92 static v8::Handle<v8::Value> GetV8SchemaForAPI(
93 ExtensionImpl* self,
94 v8::Handle<v8::Context> context,
95 const std::string& api_name) {
96 CachedSchemaMap::iterator maybe_api = self->schemas_.find(api_name);
97 if (maybe_api != self->schemas_.end())
98 return maybe_api->second;
99
100 scoped_ptr<V8ValueConverter> v8_value_converter(V8ValueConverter::create());
101 const base::DictionaryValue* schema =
102 ExtensionAPI::GetInstance()->GetSchema(api_name);
103 CHECK(schema) << api_name;
104
105 self->schemas_[api_name] =
106 v8::Persistent<v8::Object>::New(v8::Handle<v8::Object>::Cast(
107 v8_value_converter->ToV8Value(schema, context)));
108 CHECK(!self->schemas_[api_name].IsEmpty());
109
110 return self->schemas_[api_name];
111 }
112
113 static v8::Handle<v8::Value> GetExtensionAPIDefinition( 82 static v8::Handle<v8::Value> GetExtensionAPIDefinition(
114 const v8::Arguments& args) { 83 const v8::Arguments& args) {
115 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 84 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
116 ExtensionDispatcher* dispatcher = self->extension_dispatcher_; 85 ExtensionDispatcher* dispatcher = self->extension_dispatcher_;
117 86
118 ChromeV8Context* v8_context = dispatcher->v8_context_set().GetCurrent(); 87 ChromeV8Context* v8_context = dispatcher->v8_context_set().GetCurrent();
119 CHECK(v8_context); 88 CHECK(v8_context);
120 89
121 // TODO(kalman): can we just cache this in the ChromeV8Context instance?
122 scoped_ptr<std::set<std::string> > apis; 90 scoped_ptr<std::set<std::string> > apis;
123 91
124 const std::string& extension_id = v8_context->extension_id(); 92 const std::string& extension_id = v8_context->extension_id();
125 if (dispatcher->IsTestExtensionId(extension_id)) { 93 if (dispatcher->IsTestExtensionId(extension_id)) {
126 apis.reset(new std::set<std::string>()); 94 apis.reset(new std::set<std::string>());
127 // The minimal set of APIs that tests need. 95 // The minimal set of APIs that tests need.
128 apis->insert("extension"); 96 apis->insert("extension");
129 } else { 97 } else {
130 apis = ExtensionAPI::GetInstance()->GetAPIsForContext( 98 apis = ExtensionAPI::GetInstance()->GetAPIsForContext(
131 v8_context->context_type(), 99 v8_context->context_type(),
132 dispatcher->extensions()->GetByID(extension_id), 100 dispatcher->extensions()->GetByID(extension_id),
133 UserScriptSlave::GetDataSourceURLForFrame(v8_context->web_frame())); 101 UserScriptSlave::GetDataSourceURLForFrame(v8_context->web_frame()));
134 } 102 }
135 103
136 v8::Persistent<v8::Context> context(v8::Context::New()); 104 return dispatcher->v8_schema_registry()->GetSchemas(*apis);
137 v8::Context::Scope context_scope(context);
138 v8::Handle<v8::Array> api(v8::Array::New(apis->size()));
139 size_t api_index = 0;
140 for (std::set<std::string>::iterator i = apis->begin(); i != apis->end();
141 ++i) {
142 // TODO(kalman): this caching is actually useless now, because
143 // SchemaGeneratedBindings is per-context not per-process. We should
144 // (e.g.) hang a SchemaRegistry off ExtensionDispatcher (which maintains
145 // a *single* v8::Context rather than multiple ones as here).
146 api->Set(api_index, GetV8SchemaForAPI(self, context, *i));
147 ++api_index;
148 }
149
150 // The persistent extension_api_ will keep the context alive.
151 context.Dispose();
152
153 return api;
154 } 105 }
155 106
156 static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) { 107 static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) {
157 static int next_request_id = 0; 108 static int next_request_id = 0;
158 return v8::Integer::New(next_request_id++); 109 return v8::Integer::New(next_request_id++);
159 } 110 }
160 111
161 // Common code for starting an API request to the browser. |value_args| 112 // Common code for starting an API request to the browser. |value_args|
162 // contains the request's arguments. 113 // contains the request's arguments.
163 // Steals value_args contents for efficiency. 114 // Steals value_args contents for efficiency.
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 if (details->Has(v8::String::New("tabId"))) { 257 if (details->Has(v8::String::New("tabId"))) {
307 dict->SetInteger("tabId", 258 dict->SetInteger("tabId",
308 details->Get(v8::String::New("tabId"))->Int32Value()); 259 details->Get(v8::String::New("tabId"))->Int32Value());
309 } 260 }
310 261
311 ListValue list_value; 262 ListValue list_value;
312 list_value.Append(dict); 263 list_value.Append(dict);
313 264
314 return StartRequestCommon(args, &list_value); 265 return StartRequestCommon(args, &list_value);
315 } 266 }
316
317 // Cached JS Array representation of each namespace in extension_api.json.
318 // We store this so that we don't have to parse it over and over again for
319 // every context that uses it.
320 typedef std::map<std::string, v8::Persistent<v8::Object> > CachedSchemaMap;
321 CachedSchemaMap schemas_;
322 }; 267 };
323 268
324 } // namespace 269 } // namespace
325 270
326 namespace extensions { 271 namespace extensions {
327 272
328 // static 273 // static
329 ChromeV8Extension* SchemaGeneratedBindings::Get( 274 ChromeV8Extension* SchemaGeneratedBindings::Get(
330 ExtensionDispatcher* extension_dispatcher) { 275 ExtensionDispatcher* extension_dispatcher) {
331 return new ExtensionImpl(extension_dispatcher); 276 return new ExtensionImpl(extension_dispatcher);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 const std::string& extension_id) { 332 const std::string& extension_id) {
388 for (PendingRequestMap::const_iterator it = g_pending_requests.Get().begin(); 333 for (PendingRequestMap::const_iterator it = g_pending_requests.Get().begin();
389 it != g_pending_requests.Get().end(); ++it) { 334 it != g_pending_requests.Get().end(); ++it) {
390 if (it->second->extension_id == extension_id) 335 if (it->second->extension_id == extension_id)
391 return true; 336 return true;
392 } 337 }
393 return false; 338 return false;
394 } 339 }
395 340
396 } // namespace 341 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698