Chromium Code Reviews| Index: chrome/renderer/extensions/dispatcher.cc |
| diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc |
| index 930cb5d568e4bfc8812c9d484c4820e8c8efeaf5..de9691f836ee623adfd5c8cd363eca8fb2129cc9 100644 |
| --- a/chrome/renderer/extensions/dispatcher.cc |
| +++ b/chrome/renderer/extensions/dispatcher.cc |
| @@ -8,12 +8,14 @@ |
| #include "base/command_line.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/string_piece.h" |
| +#include "base/string_split.h" |
| #include "chrome/common/child_process_logging.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/chrome_version_info.h" |
| #include "chrome/common/extensions/api/extension_api.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_messages.h" |
| +#include "chrome/common/extensions/features/feature.h" |
| #include "chrome/common/extensions/manifest.h" |
| #include "chrome/common/extensions/permissions/permission_set.h" |
| #include "chrome/common/url_constants.h" |
| @@ -23,6 +25,7 @@ |
| #include "chrome/renderer/extensions/app_bindings.h" |
| #include "chrome/renderer/extensions/app_runtime_custom_bindings.h" |
| #include "chrome/renderer/extensions/app_window_custom_bindings.h" |
| +#include "chrome/renderer/extensions/binding_generating_native_handler.h" |
| #include "chrome/renderer/extensions/chrome_v8_context.h" |
| #include "chrome/renderer/extensions/chrome_v8_extension.h" |
| #include "chrome/renderer/extensions/content_watcher.h" |
| @@ -38,7 +41,7 @@ |
| #include "chrome/renderer/extensions/media_galleries_custom_bindings.h" |
| #include "chrome/renderer/extensions/miscellaneous_bindings.h" |
| #include "chrome/renderer/extensions/module_system.h" |
| -#include "chrome/renderer/extensions/native_handler.h" |
| +#include "chrome/renderer/extensions/object_backed_native_handler.h" |
| #include "chrome/renderer/extensions/page_actions_custom_bindings.h" |
| #include "chrome/renderer/extensions/page_capture_custom_bindings.h" |
| #include "chrome/renderer/extensions/request_sender.h" |
| @@ -89,24 +92,97 @@ static const char kEventDispatchFunction[] = "Event.dispatchEvent"; |
| static const char kOnSuspendEvent[] = "runtime.onSuspend"; |
| static const char kOnSuspendCanceledEvent[] = "runtime.onSuspendCanceled"; |
| -class ChromeHiddenNativeHandler : public NativeHandler { |
| +static v8::Handle<v8::Object> GetOrCreateChrome( |
| + v8::Handle<v8::Context> context) { |
| + v8::Handle<v8::String> chrome_string(v8::String::New("chrome")); |
| + v8::Handle<v8::Object> global(context->Global()); |
| + v8::Handle<v8::Value> chrome(global->Get(chrome_string)); |
| + if (chrome.IsEmpty() || chrome->IsUndefined()) { |
| + v8::Handle<v8::Object> chrome_object(v8::Object::New()); |
| + global->Set(chrome_string, chrome_object); |
| + return chrome_object; |
| + } |
| + CHECK(chrome->IsObject()); |
| + return chrome->ToObject(); |
| +} |
| + |
| +class SchemaRegistryNativeHandler : public ObjectBackedNativeHandler { |
| public: |
| - explicit ChromeHiddenNativeHandler(v8::Isolate* isolate) |
| - : NativeHandler(isolate) { |
| + SchemaRegistryNativeHandler(V8SchemaRegistry* registry, |
| + v8::Handle<v8::Context> context) |
| + : ObjectBackedNativeHandler(context), |
| + registry_(registry) { |
| + RouteFunction("GetSchema", |
| + base::Bind(&SchemaRegistryNativeHandler::GetSchema, |
| + base::Unretained(this))); |
| + } |
| + |
| + private: |
| + v8::Handle<v8::Value> GetSchema(const v8::Arguments& args) { |
| + return registry_->GetSchema(*v8::String::AsciiValue(args[0])); |
| + } |
| + |
| + V8SchemaRegistry* registry_; |
| +}; |
| + |
| +class V8ContextNativeHandler : public ObjectBackedNativeHandler { |
| + public: |
| + explicit V8ContextNativeHandler(ChromeV8Context* context) |
| + : ObjectBackedNativeHandler(context->v8_context()), |
| + context_(context) { |
| + RouteFunction("GetAvailability", |
| + base::Bind(&V8ContextNativeHandler::GetAvailability, |
| + base::Unretained(this))); |
| + } |
| + |
| + private: |
| + v8::Handle<v8::Value> GetAvailability(const v8::Arguments& args) { |
| + CHECK_EQ(args.Length(), 1); |
| + std::string api_name = *v8::String::AsciiValue(args[0]->ToString()); |
| + Feature::Availability availability = context_->GetAvailability(api_name); |
| + |
| + v8::Handle<v8::Object> ret = v8::Object::New(); |
| + ret->Set(v8::String::New("is_available"), |
| + v8::Boolean::New(availability.is_available())); |
| + ret->Set(v8::String::New("message"), |
| + v8::String::New(availability.message().c_str())); |
| + return ret; |
| + } |
| + |
| + ChromeV8Context* context_; |
| +}; |
| + |
| +class ChromeHiddenNativeHandler : public ObjectBackedNativeHandler { |
| + public: |
| + explicit ChromeHiddenNativeHandler(v8::Handle<v8::Context> context) |
| + : ObjectBackedNativeHandler(context) { |
| RouteFunction("GetChromeHidden", |
| base::Bind(&ChromeHiddenNativeHandler::GetChromeHidden, |
| base::Unretained(this))); |
| } |
| v8::Handle<v8::Value> GetChromeHidden(const v8::Arguments& args) { |
| - return ChromeV8Context::GetOrCreateChromeHidden(v8::Context::GetCurrent()); |
| + return ChromeV8Context::GetOrCreateChromeHidden(v8_context()); |
| } |
| }; |
| -class PrintNativeHandler : public NativeHandler { |
| +class ChromeNativeHandler : public ObjectBackedNativeHandler { |
| public: |
| - explicit PrintNativeHandler(v8::Isolate* isolate) |
| - : NativeHandler(isolate) { |
| + explicit ChromeNativeHandler(v8::Handle<v8::Context> context) |
| + : ObjectBackedNativeHandler(context) { |
| + RouteFunction("GetChrome", |
| + base::Bind(&ChromeNativeHandler::GetChrome, base::Unretained(this))); |
| + } |
| + |
| + v8::Handle<v8::Value> GetChrome(const v8::Arguments& args) { |
| + return GetOrCreateChrome(v8_context()); |
| + } |
| +}; |
| + |
| +class PrintNativeHandler : public ObjectBackedNativeHandler { |
| + public: |
| + explicit PrintNativeHandler(v8::Handle<v8::Context> context) |
| + : ObjectBackedNativeHandler(context) { |
| RouteFunction("Print", |
| base::Bind(&PrintNativeHandler::Print, |
| base::Unretained(this))); |
| @@ -138,7 +214,8 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension { |
| } |
| v8::Handle<v8::Value> IncrementKeepaliveCount(const v8::Arguments& args) { |
| - ChromeV8Context* context = dispatcher()->v8_context_set().GetCurrent(); |
| + ChromeV8Context* context = |
| + dispatcher()->v8_context_set().GetByV8Context(v8_context()); |
| if (!context) |
| return v8::Undefined(); |
| RenderView* render_view = context->GetRenderView(); |
| @@ -150,7 +227,8 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension { |
| } |
| v8::Handle<v8::Value> DecrementKeepaliveCount(const v8::Arguments& args) { |
| - ChromeV8Context* context = dispatcher()->v8_context_set().GetCurrent(); |
| + ChromeV8Context* context = |
| + dispatcher()->v8_context_set().GetByV8Context(v8_context()); |
| if (!context) |
| return v8::Undefined(); |
| RenderView* render_view = context->GetRenderView(); |
| @@ -238,13 +316,12 @@ class ProcessInfoNativeHandler : public ChromeV8Extension { |
| bool send_request_disabled_; |
| }; |
| -class LoggingNativeHandler : public NativeHandler { |
| +class LoggingNativeHandler : public ObjectBackedNativeHandler { |
| public: |
| - explicit LoggingNativeHandler(v8::Isolate* isolate) |
| - : NativeHandler(isolate) { |
| + explicit LoggingNativeHandler(v8::Handle<v8::Context> context) |
| + : ObjectBackedNativeHandler(context) { |
| RouteFunction("DCHECK", |
| - base::Bind(&LoggingNativeHandler::Dcheck, |
| - base::Unretained(this))); |
| + base::Bind(&LoggingNativeHandler::Dcheck, base::Unretained(this))); |
| } |
| v8::Handle<v8::Value> Dcheck(const v8::Arguments& args) { |
| @@ -270,7 +347,6 @@ class LoggingNativeHandler : public NativeHandler { |
| } |
| } |
| DCHECK(check_value) << error_message; |
| - LOG(WARNING) << error_message; |
| return v8::Undefined(); |
| } |
| @@ -302,20 +378,6 @@ void InstallWebstoreBindings(ModuleSystem* module_system, |
| "chromeHiddenWebstore"); |
| } |
| -static v8::Handle<v8::Object> GetOrCreateChrome( |
| - v8::Handle<v8::Context> context) { |
| - v8::Handle<v8::String> chrome_string(v8::String::New("chrome")); |
| - v8::Handle<v8::Object> global(context->Global()); |
| - v8::Handle<v8::Value> chrome(global->Get(chrome_string)); |
| - if (chrome.IsEmpty() || chrome->IsUndefined()) { |
| - v8::Handle<v8::Object> chrome_object(v8::Object::New()); |
| - global->Set(chrome_string, chrome_object); |
| - return chrome_object; |
| - } |
| - CHECK(chrome->IsObject()); |
| - return chrome->ToObject(); |
| -} |
| - |
| } // namespace |
| Dispatcher::Dispatcher() |
| @@ -336,7 +398,7 @@ Dispatcher::Dispatcher() |
| } |
| user_script_slave_.reset(new UserScriptSlave(&extensions_)); |
| - request_sender_.reset(new RequestSender(this, &v8_context_set_)); |
| + request_sender_.reset(new RequestSender(this)); |
| PopulateSourceMap(); |
| PopulateLazyBindingsMap(); |
| } |
| @@ -560,58 +622,128 @@ bool Dispatcher::AllowScriptExtension(WebFrame* frame, |
| return true; |
| } |
| +v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( |
| + v8::Handle<v8::Object> object, |
| + const std::string& field) { |
| + v8::HandleScope handle_scope; |
| + v8::Handle<v8::String> key = v8::String::New(field.c_str()); |
| + // This little dance is for APIs that may be unavailable but have available |
| + // children. For example, chrome.app can be unavailable, while |
| + // chrome.app.runtime is available. The lazy getter for chrome.app must be |
| + // deleted, so that there isn't an error when accessing chrome.app.runtime. |
| + if (object->Has(key)) { |
| + v8::Handle<v8::Value> value = object->Get(key); |
| + if (!value->IsUndefined() && value->IsObject()) |
|
not at google - send to devlin
2013/03/01 00:36:06
I think that IsObject implies !undefined so the fi
cduvall
2013/03/01 00:43:52
Done.
|
| + return handle_scope.Close(v8::Handle<v8::Object>::Cast(value)); |
| + else |
| + object->Delete(key); |
| + } |
| + |
| + v8::Handle<v8::Object> new_object = v8::Object::New(); |
| + object->Set(key, new_object); |
| + return handle_scope.Close(new_object); |
| +} |
| + |
| +void Dispatcher::RegisterSchemaGeneratedBindings( |
| + ModuleSystem* module_system, |
| + ChromeV8Context* context, |
| + v8::Handle<v8::Context> v8_context) { |
| + std::set<std::string> apis = |
| + ExtensionAPI::GetSharedInstance()->GetAllAPINames(); |
| + for (std::set<std::string>::iterator it = apis.begin(); |
| + it != apis.end(); ++it) { |
| + const std::string& api_name = *it; |
| + |
| + std::vector<std::string> split; |
| + base::SplitString(api_name, '.', &split); |
| + |
| + v8::Handle<v8::Object> bind_object = GetOrCreateChrome(v8_context); |
| + for (size_t i = 0; i < split.size() - 1; ++i) |
| + bind_object = GetOrCreateObject(bind_object, split[i]); |
| + |
| + if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) { |
| + InstallBindings(module_system, v8_context, api_name); |
| + } else if (!source_map_.Contains(api_name)) { |
| + module_system->RegisterNativeHandler( |
| + api_name, |
| + scoped_ptr<NativeHandler>(new BindingGeneratingNativeHandler( |
| + module_system, |
| + api_name, |
| + "binding"))); |
| + module_system->SetNativeLazyField(bind_object, |
| + split.back(), |
| + api_name, |
| + "binding"); |
| + } else { |
| + module_system->SetLazyField(bind_object, |
| + split.back(), |
| + api_name, |
| + "binding"); |
| + } |
| + } |
| +} |
| + |
| void Dispatcher::RegisterNativeHandlers(ModuleSystem* module_system, |
| ChromeV8Context* context) { |
| module_system->RegisterNativeHandler("event_bindings", |
| - scoped_ptr<NativeHandler>(EventBindings::Get(this))); |
| + scoped_ptr<NativeHandler>( |
| + EventBindings::Create(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("miscellaneous_bindings", |
| - scoped_ptr<NativeHandler>(MiscellaneousBindings::Get(this))); |
| + scoped_ptr<NativeHandler>( |
| + MiscellaneousBindings::Get(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("apiDefinitions", |
| - scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this))); |
| + scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this, context))); |
| module_system->RegisterNativeHandler("sendRequest", |
| scoped_ptr<NativeHandler>( |
| - new SendRequestNatives(this, request_sender_.get()))); |
| + new SendRequestNatives(this, request_sender_.get(), context))); |
| module_system->RegisterNativeHandler("setIcon", |
| scoped_ptr<NativeHandler>( |
| - new SetIconNatives(this, request_sender_.get()))); |
| + new SetIconNatives(this, request_sender_.get(), context))); |
| module_system->RegisterNativeHandler("contentWatcherNative", |
| content_watcher_->MakeNatives()); |
| // Natives used by multiple APIs. |
| module_system->RegisterNativeHandler("file_system_natives", |
| - scoped_ptr<NativeHandler>(new FileSystemNatives())); |
| + scoped_ptr<NativeHandler>(new FileSystemNatives(context->v8_context()))); |
| // Custom bindings. |
| module_system->RegisterNativeHandler("app", |
| scoped_ptr<NativeHandler>(new AppBindings(this, context))); |
| module_system->RegisterNativeHandler("app_runtime", |
| - scoped_ptr<NativeHandler>(new AppRuntimeCustomBindings())); |
| + scoped_ptr<NativeHandler>( |
| + new AppRuntimeCustomBindings(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("app_window", |
| - scoped_ptr<NativeHandler>(new AppWindowCustomBindings(this))); |
| + scoped_ptr<NativeHandler>( |
| + new AppWindowCustomBindings(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("context_menus", |
| scoped_ptr<NativeHandler>(new ContextMenusCustomBindings())); |
| module_system->RegisterNativeHandler("extension", |
| scoped_ptr<NativeHandler>( |
| - new ExtensionCustomBindings(this))); |
| + new ExtensionCustomBindings(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("sync_file_system", |
| scoped_ptr<NativeHandler>(new SyncFileSystemCustomBindings())); |
| module_system->RegisterNativeHandler("file_browser_handler", |
| - scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings())); |
| + scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings( |
| + context->v8_context()))); |
| module_system->RegisterNativeHandler("file_browser_private", |
| - scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings())); |
| + scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings( |
| + context->v8_context()))); |
| module_system->RegisterNativeHandler("i18n", |
| - scoped_ptr<NativeHandler>(new I18NCustomBindings())); |
| + scoped_ptr<NativeHandler>( |
| + new I18NCustomBindings(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("mediaGalleries", |
| scoped_ptr<NativeHandler>(new MediaGalleriesCustomBindings())); |
| module_system->RegisterNativeHandler("page_actions", |
| scoped_ptr<NativeHandler>( |
| new PageActionsCustomBindings(this))); |
| module_system->RegisterNativeHandler("page_capture", |
| - scoped_ptr<NativeHandler>(new PageCaptureCustomBindings())); |
| + scoped_ptr<NativeHandler>( |
| + new PageCaptureCustomBindings(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("runtime", |
| - scoped_ptr<NativeHandler>(new RuntimeCustomBindings(context))); |
| + scoped_ptr<NativeHandler>(new RuntimeCustomBindings(this, context))); |
| module_system->RegisterNativeHandler("tabs", |
| - scoped_ptr<NativeHandler>(new TabsCustomBindings())); |
| + scoped_ptr<NativeHandler>( |
| + new TabsCustomBindings(this, context->v8_context()))); |
| module_system->RegisterNativeHandler("tts", |
| scoped_ptr<NativeHandler>(new TTSCustomBindings())); |
| module_system->RegisterNativeHandler("web_request", |
| @@ -624,11 +756,9 @@ void Dispatcher::PopulateSourceMap() { |
| source_map_.RegisterSource("event_bindings", IDR_EVENT_BINDINGS_JS); |
| source_map_.RegisterSource("miscellaneous_bindings", |
| IDR_MISCELLANEOUS_BINDINGS_JS); |
| - source_map_.RegisterSource("schema_generated_bindings", |
| - IDR_SCHEMA_GENERATED_BINDINGS_JS); |
| source_map_.RegisterSource("json", IDR_JSON_JS); |
| source_map_.RegisterSource("json_schema", IDR_JSON_SCHEMA_JS); |
| - source_map_.RegisterSource("apitest", IDR_EXTENSION_APITEST_JS); |
| + source_map_.RegisterSource("test", IDR_TEST_CUSTOM_BINDINGS_JS); |
| // Libraries. |
| source_map_.RegisterSource("contentWatcher", IDR_CONTENT_WATCHER_JS); |
| @@ -695,10 +825,11 @@ void Dispatcher::PopulateSourceMap() { |
| source_map_.RegisterSource("webRequestInternal", |
| IDR_WEB_REQUEST_INTERNAL_CUSTOM_BINDINGS_JS); |
| source_map_.RegisterSource("webstore", IDR_WEBSTORE_CUSTOM_BINDINGS_JS); |
| + source_map_.RegisterSource("binding", IDR_BINDING_JS); |
| // Platform app sources that are not API-specific.. |
| source_map_.RegisterSource("tagWatcher", IDR_TAG_WATCHER_JS); |
| - source_map_.RegisterSource("webview", IDR_WEB_VIEW_JS); |
| + source_map_.RegisterSource("web_view", IDR_WEB_VIEW_JS); |
| source_map_.RegisterSource("denyWebview", IDR_WEB_VIEW_DENY_JS); |
| source_map_.RegisterSource("platformApp", IDR_PLATFORM_APP_JS); |
| source_map_.RegisterSource("injectAppTitlebar", IDR_INJECT_APP_TITLEBAR_JS); |
| @@ -771,15 +902,21 @@ void Dispatcher::DidCreateScriptContext( |
| RegisterNativeHandlers(module_system.get(), context); |
| - v8::Isolate* isolate = v8_context->GetIsolate(); |
| + module_system->RegisterNativeHandler("chrome", |
| + scoped_ptr<NativeHandler>(new ChromeNativeHandler(v8_context))); |
| module_system->RegisterNativeHandler("chrome_hidden", |
| - scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(isolate))); |
| + scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(v8_context))); |
| module_system->RegisterNativeHandler("print", |
| - scoped_ptr<NativeHandler>(new PrintNativeHandler(isolate))); |
| + scoped_ptr<NativeHandler>(new PrintNativeHandler(v8_context))); |
| module_system->RegisterNativeHandler("lazy_background_page", |
| scoped_ptr<NativeHandler>(new LazyBackgroundPageNativeHandler(this))); |
| module_system->RegisterNativeHandler("logging", |
| - scoped_ptr<NativeHandler>(new LoggingNativeHandler(isolate))); |
| + scoped_ptr<NativeHandler>(new LoggingNativeHandler(v8_context))); |
| + module_system->RegisterNativeHandler("schema_registry", |
| + scoped_ptr<NativeHandler>( |
| + new SchemaRegistryNativeHandler(v8_schema_registry(), v8_context))); |
| + module_system->RegisterNativeHandler("v8_context", |
| + scoped_ptr<NativeHandler>(new V8ContextNativeHandler(context))); |
| int manifest_version = extension ? extension->manifest_version() : 1; |
| bool send_request_disabled = |
| @@ -803,25 +940,20 @@ void Dispatcher::DidCreateScriptContext( |
| InstallBindings(module_system.get(), v8_context, "app"); |
| InstallBindings(module_system.get(), v8_context, "webstore"); |
| break; |
| - |
| case Feature::BLESSED_EXTENSION_CONTEXT: |
| case Feature::UNBLESSED_EXTENSION_CONTEXT: |
| case Feature::CONTENT_SCRIPT_CONTEXT: { |
| + if (extension && !extension->is_platform_app()) |
| + module_system->Require("miscellaneous_bindings"); |
| module_system->Require("json"); // see paranoid comment in json.js |
| - module_system->Require("miscellaneous_bindings"); |
| - module_system->Require("schema_generated_bindings"); |
| - module_system->Require("apitest"); |
| // TODO(kalman): move this code back out of the switch and execute it |
| // regardless of |context_type|. ExtensionAPI knows how to return the |
| // correct APIs, however, until it doesn't have a 2MB overhead we can't |
| // load it in every process. |
| - const std::set<std::string>& apis = context->GetAvailableExtensionAPIs(); |
| - for (std::set<std::string>::const_iterator i = apis.begin(); |
| - i != apis.end(); ++i) { |
| - InstallBindings(module_system.get(), v8_context, *i); |
| - } |
| - |
| + RegisterSchemaGeneratedBindings(module_system.get(), |
| + context, |
| + v8_context); |
| break; |
| } |
| } |
| @@ -832,7 +964,7 @@ void Dispatcher::DidCreateScriptContext( |
| if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) { |
| bool has_permission = extension->HasAPIPermission(APIPermission::kWebView); |
| - module_system->Require(has_permission ? "webview" : "denyWebview"); |
| + module_system->Require(has_permission ? "web_view" : "denyWebview"); |
| } |
| context->set_module_system(module_system.Pass()); |
| @@ -873,6 +1005,8 @@ void Dispatcher::WillReleaseScriptContext( |
| return; |
| context->DispatchOnUnloadEvent(); |
| + // TODO(kalman): add an invalidation observer interface to ChromeV8Context. |
| + request_sender_->InvalidateContext(context); |
| v8_context_set_.Remove(context); |
| VLOG(1) << "Num tracked contexts: " << v8_context_set_.size(); |
| @@ -1109,9 +1243,8 @@ void Dispatcher::OnExtensionResponse(int request_id, |
| request_sender_->HandleResponse(request_id, success, response, error); |
| } |
| -bool Dispatcher::CheckCurrentContextAccessToExtensionAPI( |
| - const std::string& function_name) const { |
| - ChromeV8Context* context = v8_context_set().GetCurrent(); |
| +bool Dispatcher::CheckContextAccessToExtensionAPI( |
| + const std::string& function_name, ChromeV8Context* context) const { |
| if (!context) { |
| DLOG(ERROR) << "Not in a v8::Context"; |
| return false; |