| Index: extensions/renderer/object_backed_native_handler.cc
|
| diff --git a/extensions/renderer/object_backed_native_handler.cc b/extensions/renderer/object_backed_native_handler.cc
|
| index 109fae18d7f32ae2757b1259b19ea57db65f6bb0..23be1d6789e88bfedfa253fcd8040f77f3fa7cd0 100644
|
| --- a/extensions/renderer/object_backed_native_handler.cc
|
| +++ b/extensions/renderer/object_backed_native_handler.cc
|
| @@ -8,10 +8,12 @@
|
|
|
| #include "base/logging.h"
|
| #include "base/memory/linked_ptr.h"
|
| +#include "content/public/child/worker_thread.h"
|
| #include "extensions/renderer/console.h"
|
| #include "extensions/renderer/module_system.h"
|
| #include "extensions/renderer/script_context.h"
|
| #include "extensions/renderer/script_context_set.h"
|
| +#include "extensions/renderer/v8_helpers.h"
|
| #include "v8/include/v8.h"
|
|
|
| namespace extensions {
|
| @@ -19,6 +21,7 @@ namespace extensions {
|
| namespace {
|
| // Key for the base::Bound routed function.
|
| const char* kHandlerFunction = "handler_function";
|
| +const char* kFeatureName = "feature_name";
|
| } // namespace
|
|
|
| ObjectBackedNativeHandler::ObjectBackedNativeHandler(ScriptContext* context)
|
| @@ -45,15 +48,36 @@ void ObjectBackedNativeHandler::Router(
|
| v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
|
|
| v8::Local<v8::Value> handler_function_value;
|
| + v8::Local<v8::Value> feature_name_value;
|
| // See comment in header file for why we do this.
|
| if (!GetPrivate(context, data, kHandlerFunction, &handler_function_value) ||
|
| - handler_function_value->IsUndefined()) {
|
| + handler_function_value->IsUndefined() ||
|
| + !GetPrivate(context, data, kFeatureName, &feature_name_value) ||
|
| + !feature_name_value->IsString()) {
|
| ScriptContext* script_context =
|
| ScriptContextSet::GetContextByV8Context(context);
|
| console::Error(script_context ? script_context->GetRenderFrame() : nullptr,
|
| "Extension view no longer exists");
|
| return;
|
| }
|
| +
|
| + // We can't access the ScriptContextSet on a worker thread. Luckily, we also
|
| + // don't inject many bindings into worker threads.
|
| + // TODO(devlin): Figure out a way around this.
|
| + if (content::WorkerThread::GetCurrentId() == 0) {
|
| + ScriptContext* script_context =
|
| + ScriptContextSet::GetContextByV8Context(context);
|
| + v8::Local<v8::String> feature_name_string =
|
| + feature_name_value->ToString(context).ToLocalChecked();
|
| + std::string feature_name = *v8::String::Utf8Value(feature_name_string);
|
| + // TODO(devlin): Eventually, we should fail if either script_context is null
|
| + // or feature_name is empty.
|
| + if (script_context &&
|
| + !feature_name.empty() &&
|
| + !script_context->GetAvailability(feature_name).is_available()) {
|
| + return;
|
| + }
|
| + }
|
| // This CHECK is *important*. Otherwise, we'll go around happily executing
|
| // something random. See crbug.com/548273.
|
| CHECK(handler_function_value->IsExternal());
|
| @@ -64,6 +88,13 @@ void ObjectBackedNativeHandler::Router(
|
| void ObjectBackedNativeHandler::RouteFunction(
|
| const std::string& name,
|
| const HandlerFunction& handler_function) {
|
| + RouteFunction(name, "", handler_function);
|
| +}
|
| +
|
| +void ObjectBackedNativeHandler::RouteFunction(
|
| + const std::string& name,
|
| + const std::string& feature_name,
|
| + const HandlerFunction& handler_function) {
|
| v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| v8::HandleScope handle_scope(isolate);
|
| v8::Context::Scope context_scope(context_->v8_context());
|
| @@ -71,6 +102,8 @@ void ObjectBackedNativeHandler::RouteFunction(
|
| v8::Local<v8::Object> data = v8::Object::New(isolate);
|
| SetPrivate(data, kHandlerFunction,
|
| v8::External::New(isolate, new HandlerFunction(handler_function)));
|
| + SetPrivate(data, kFeatureName,
|
| + v8_helpers::ToV8StringUnsafe(isolate, feature_name));
|
| v8::Local<v8::FunctionTemplate> function_template =
|
| v8::FunctionTemplate::New(isolate, Router, data);
|
| v8::Local<v8::ObjectTemplate>::New(isolate, object_template_)
|
|
|