Commit 9ff5b9c5 authored by Devlin Cronin's avatar Devlin Cronin Committed by Commit Bot

[Extensions Bindings] Add a thread-friendly ScriptContext getter

Add a common ScriptContext getter to retrieve a ScriptContext from a
given v8::Context that works across threads. This previously existed,
but only in native_extension_bindings_system.cc. Pull it out to a common
file to a) make it reusable from other consumers (custom hooks will need
to use this) and b) remove (direct) threading knowledge from the bindings
system.

Bug: 653596

Change-Id: I09a0e4ea76bb891ab1871ca1deb0d315e6e9789d
Reviewed-on: https://chromium-review.googlesource.com/812173Reviewed-by: default avatarIstiaque Ahmed <lazyboy@chromium.org>
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#522243}
parent e291d73a
...@@ -10,11 +10,11 @@ ...@@ -10,11 +10,11 @@
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/manifest.h" #include "extensions/common/manifest.h"
#include "extensions/renderer/bindings/api_signature.h" #include "extensions/renderer/bindings/api_signature.h"
#include "extensions/renderer/get_script_context.h"
#include "extensions/renderer/message_target.h" #include "extensions/renderer/message_target.h"
#include "extensions/renderer/messaging_util.h" #include "extensions/renderer/messaging_util.h"
#include "extensions/renderer/native_renderer_messaging_service.h" #include "extensions/renderer/native_renderer_messaging_service.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h"
#include "gin/converter.h" #include "gin/converter.h"
namespace extensions { namespace extensions {
...@@ -112,9 +112,7 @@ RequestResult ExtensionHooksDelegate::HandleRequest( ...@@ -112,9 +112,7 @@ RequestResult ExtensionHooksDelegate::HandleRequest(
// TODO(devlin): Add getBackgroundPage, getExtensionTabs, getViews. // TODO(devlin): Add getBackgroundPage, getExtensionTabs, getViews.
}; };
ScriptContext* script_context = ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
ScriptContextSet::GetContextByV8Context(context);
DCHECK(script_context);
Handler handler = nullptr; Handler handler = nullptr;
for (const auto& handler_entry : kHandlers) { for (const auto& handler_entry : kHandlers) {
...@@ -166,7 +164,7 @@ void ExtensionHooksDelegate::InitializeInstance( ...@@ -166,7 +164,7 @@ void ExtensionHooksDelegate::InitializeInstance(
// isn't terribly efficient, but is only done for certain unpacked extensions // isn't terribly efficient, but is only done for certain unpacked extensions
// and only if they access the chrome.extension module. // and only if they access the chrome.extension module.
if (messaging_util::IsSendRequestDisabled( if (messaging_util::IsSendRequestDisabled(
ScriptContextSet::GetContextByV8Context(context))) { GetScriptContextFromV8ContextChecked(context))) {
static constexpr const char* kDeprecatedSendRequestProperties[] = { static constexpr const char* kDeprecatedSendRequestProperties[] = {
"sendRequest", "onRequest", "onRequestExternal"}; "sendRequest", "onRequest", "onRequestExternal"};
for (const char* property : kDeprecatedSendRequestProperties) { for (const char* property : kDeprecatedSendRequestProperties) {
......
...@@ -10,11 +10,11 @@ ...@@ -10,11 +10,11 @@
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/manifest.h" #include "extensions/common/manifest.h"
#include "extensions/renderer/bindings/api_signature.h" #include "extensions/renderer/bindings/api_signature.h"
#include "extensions/renderer/get_script_context.h"
#include "extensions/renderer/message_target.h" #include "extensions/renderer/message_target.h"
#include "extensions/renderer/messaging_util.h" #include "extensions/renderer/messaging_util.h"
#include "extensions/renderer/native_renderer_messaging_service.h" #include "extensions/renderer/native_renderer_messaging_service.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h"
#include "gin/converter.h" #include "gin/converter.h"
namespace extensions { namespace extensions {
...@@ -53,9 +53,7 @@ RequestResult TabsHooksDelegate::HandleRequest( ...@@ -53,9 +53,7 @@ RequestResult TabsHooksDelegate::HandleRequest(
{&TabsHooksDelegate::HandleConnect, kConnect}, {&TabsHooksDelegate::HandleConnect, kConnect},
}; };
ScriptContext* script_context = ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
ScriptContextSet::GetContextByV8Context(context);
DCHECK(script_context);
Handler handler = nullptr; Handler handler = nullptr;
for (const auto& handler_entry : kHandlers) { for (const auto& handler_entry : kHandlers) {
......
...@@ -118,6 +118,8 @@ source_set("renderer") { ...@@ -118,6 +118,8 @@ source_set("renderer") {
"file_system_natives.h", "file_system_natives.h",
"gc_callback.cc", "gc_callback.cc",
"gc_callback.h", "gc_callback.h",
"get_script_context.cc",
"get_script_context.h",
"gin_port.cc", "gin_port.cc",
"gin_port.h", "gin_port.h",
"guest_view/extensions_guest_view_container.cc", "guest_view/extensions_guest_view_container.cc",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/renderer/get_script_context.h"
#include "base/logging.h"
#include "content/public/renderer/worker_thread.h"
#include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h"
#include "extensions/renderer/worker_thread_dispatcher.h"
namespace extensions {
ScriptContext* GetScriptContextFromV8Context(v8::Local<v8::Context> context) {
ScriptContext* script_context =
content::WorkerThread::GetCurrentId() > 0
? WorkerThreadDispatcher::GetScriptContext()
: ScriptContextSet::GetContextByV8Context(context);
DCHECK(!script_context || script_context->v8_context() == context);
return script_context;
}
ScriptContext* GetScriptContextFromV8ContextChecked(
v8::Local<v8::Context> context) {
ScriptContext* script_context = GetScriptContextFromV8Context(context);
CHECK(script_context);
return script_context;
}
} // namespace extensions
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_RENDERER_GET_SCRIPT_CONTEXT_H_
#define EXTENSIONS_RENDERER_GET_SCRIPT_CONTEXT_H_
#include "v8/include/v8.h"
namespace extensions {
class ScriptContext;
// TODO(devlin): This is a very random place for these. But there's not really
// a better one - ScriptContextSet is (currently) thread-agnostic, and it'd be
// nice to avoid changing that.
// Returns the ScriptContext associated with the given v8::Context. This is
// designed to work for both main thread and worker thread contexts.
ScriptContext* GetScriptContextFromV8Context(v8::Local<v8::Context> context);
// Same as above, but CHECK()s the result before returning.
ScriptContext* GetScriptContextFromV8ContextChecked(
v8::Local<v8::Context> context);
} // namespace extensions
#endif // EXTENSIONS_RENDERER_GET_SCRIPT_CONTEXT_H_
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "base/timer/elapsed_timer.h" #include "base/timer/elapsed_timer.h"
#include "content/public/common/console_message_level.h" #include "content/public/common/console_message_level.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/renderer/worker_thread.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "extensions/common/event_filtering_info.h" #include "extensions/common/event_filtering_info.h"
#include "extensions/common/extension_api.h" #include "extensions/common/extension_api.h"
...@@ -29,13 +28,12 @@ ...@@ -29,13 +28,12 @@
#include "extensions/renderer/easy_unlock_proximity_required_stub.h" #include "extensions/renderer/easy_unlock_proximity_required_stub.h"
#include "extensions/renderer/extension_frame_helper.h" #include "extensions/renderer/extension_frame_helper.h"
#include "extensions/renderer/extension_js_runner.h" #include "extensions/renderer/extension_js_runner.h"
#include "extensions/renderer/get_script_context.h"
#include "extensions/renderer/ipc_message_sender.h" #include "extensions/renderer/ipc_message_sender.h"
#include "extensions/renderer/module_system.h" #include "extensions/renderer/module_system.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h"
#include "extensions/renderer/storage_area.h" #include "extensions/renderer/storage_area.h"
#include "extensions/renderer/web_request_hooks.h" #include "extensions/renderer/web_request_hooks.h"
#include "extensions/renderer/worker_thread_dispatcher.h"
#include "gin/converter.h" #include "gin/converter.h"
#include "gin/handle.h" #include "gin/handle.h"
#include "gin/per_context_data.h" #include "gin/per_context_data.h"
...@@ -152,32 +150,13 @@ BindingsSystemPerContextData* GetBindingsDataFromContext( ...@@ -152,32 +150,13 @@ BindingsSystemPerContextData* GetBindingsDataFromContext(
return data; return data;
} }
// Returns the ScriptContext associated with the given v8::Context.
// TODO(devlin): Does this belong here, or should it be curried in as a
// callback? This is the only place we have knowledge of worker vs. non-worker
// threads here.
ScriptContext* GetScriptContext(v8::Local<v8::Context> context) {
ScriptContext* script_context =
content::WorkerThread::GetCurrentId() > 0
? WorkerThreadDispatcher::GetScriptContext()
: ScriptContextSet::GetContextByV8Context(context);
DCHECK(!script_context || script_context->v8_context() == context);
return script_context;
}
// Same as above, but CHECKs the result.
ScriptContext* GetScriptContextChecked(v8::Local<v8::Context> context) {
ScriptContext* script_context = GetScriptContext(context);
CHECK(script_context);
return script_context;
}
void AddConsoleError(v8::Local<v8::Context> context, const std::string& error) { void AddConsoleError(v8::Local<v8::Context> context, const std::string& error) {
ScriptContext* script_context = GetScriptContext(context); ScriptContext* script_context = GetScriptContextFromV8Context(context);
// Note: |script_context| may be null. During context tear down, we remove the // Note: |script_context| may be null. During context tear down, we remove the
// script context from the ScriptContextSet, so it's not findable by // script context from the ScriptContextSet, so it's not findable by
// GetScriptContext. In theory, we shouldn't be running any bindings code // GetScriptContextFromV8Context. In theory, we shouldn't be running any
// after this point, but it seems that we are in at least some places. // bindings code after this point, but it seems that we are in at least some
// places.
// TODO(devlin): Investigate. At least one place this manifests is in // TODO(devlin): Investigate. At least one place this manifests is in
// messaging binding tear down exhibited by // messaging binding tear down exhibited by
// MessagingApiTest.MessagingBackgroundOnly. // MessagingApiTest.MessagingBackgroundOnly.
...@@ -198,7 +177,7 @@ const base::DictionaryValue& GetAPISchema(const std::string& api_name) { ...@@ -198,7 +177,7 @@ const base::DictionaryValue& GetAPISchema(const std::string& api_name) {
// |context|. // |context|.
bool IsAPIFeatureAvailable(v8::Local<v8::Context> context, bool IsAPIFeatureAvailable(v8::Local<v8::Context> context,
const std::string& name) { const std::string& name) {
ScriptContext* script_context = GetScriptContextChecked(context); ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
return script_context->GetAvailability(name).is_available(); return script_context->GetAvailability(name).is_available();
} }
...@@ -624,7 +603,7 @@ v8::Local<v8::Object> NativeExtensionBindingsSystem::GetAPIHelper( ...@@ -624,7 +603,7 @@ v8::Local<v8::Object> NativeExtensionBindingsSystem::GetAPIHelper(
return value.As<v8::Object>(); return value.As<v8::Object>();
} }
ScriptContext* script_context = GetScriptContextChecked(context); ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
std::string api_name_string; std::string api_name_string;
CHECK( CHECK(
gin::Converter<std::string>::FromV8(isolate, api_name, &api_name_string)); gin::Converter<std::string>::FromV8(isolate, api_name, &api_name_string));
...@@ -697,7 +676,7 @@ void NativeExtensionBindingsSystem::GetInternalAPI( ...@@ -697,7 +676,7 @@ void NativeExtensionBindingsSystem::GetInternalAPI(
std::string api_name = gin::V8ToString(info[0]); std::string api_name = gin::V8ToString(info[0]);
const Feature* feature = FeatureProvider::GetAPIFeature(api_name); const Feature* feature = FeatureProvider::GetAPIFeature(api_name);
ScriptContext* script_context = GetScriptContextChecked(context); ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
if (!feature || if (!feature ||
!script_context->IsAnyFeatureAvailableToContext( !script_context->IsAnyFeatureAvailableToContext(
*feature, CheckAliasStatus::NOT_ALLOWED)) { *feature, CheckAliasStatus::NOT_ALLOWED)) {
...@@ -729,7 +708,7 @@ void NativeExtensionBindingsSystem::GetInternalAPI( ...@@ -729,7 +708,7 @@ void NativeExtensionBindingsSystem::GetInternalAPI(
void NativeExtensionBindingsSystem::SendRequest( void NativeExtensionBindingsSystem::SendRequest(
std::unique_ptr<APIRequestHandler::Request> request, std::unique_ptr<APIRequestHandler::Request> request,
v8::Local<v8::Context> context) { v8::Local<v8::Context> context) {
ScriptContext* script_context = GetScriptContextChecked(context); ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
GURL url; GURL url;
blink::WebLocalFrame* frame = script_context->web_frame(); blink::WebLocalFrame* frame = script_context->web_frame();
...@@ -760,7 +739,7 @@ void NativeExtensionBindingsSystem::OnEventListenerChanged( ...@@ -760,7 +739,7 @@ void NativeExtensionBindingsSystem::OnEventListenerChanged(
const base::DictionaryValue* filter, const base::DictionaryValue* filter,
bool update_lazy_listeners, bool update_lazy_listeners,
v8::Local<v8::Context> context) { v8::Local<v8::Context> context) {
ScriptContext* script_context = GetScriptContextChecked(context); ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
// Note: Check context_type() first to avoid accessing ExtensionFrameHelper on // Note: Check context_type() first to avoid accessing ExtensionFrameHelper on
// a worker thread. // a worker thread.
bool is_lazy = bool is_lazy =
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/manifest.h" #include "extensions/common/manifest.h"
#include "extensions/renderer/bindings/api_signature.h" #include "extensions/renderer/bindings/api_signature.h"
#include "extensions/renderer/get_script_context.h"
#include "extensions/renderer/message_target.h" #include "extensions/renderer/message_target.h"
#include "extensions/renderer/messaging_util.h" #include "extensions/renderer/messaging_util.h"
#include "extensions/renderer/native_renderer_messaging_service.h" #include "extensions/renderer/native_renderer_messaging_service.h"
...@@ -31,8 +32,7 @@ void GetExtensionId(v8::Local<v8::Name> property_name, ...@@ -31,8 +32,7 @@ void GetExtensionId(v8::Local<v8::Name> property_name,
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = info.Holder()->CreationContext(); v8::Local<v8::Context> context = info.Holder()->CreationContext();
ScriptContext* script_context = ScriptContext* script_context = GetScriptContextFromV8Context(context);
ScriptContextSet::GetContextByV8Context(context);
// This could potentially be invoked after the script context is removed // This could potentially be invoked after the script context is removed
// (unlike the handler calls, which should only be invoked for valid // (unlike the handler calls, which should only be invoked for valid
// contexts). // contexts).
...@@ -76,9 +76,7 @@ RequestResult RuntimeHooksDelegate::HandleRequest( ...@@ -76,9 +76,7 @@ RequestResult RuntimeHooksDelegate::HandleRequest(
{&RuntimeHooksDelegate::HandleSendNativeMessage, kSendNativeMessage}, {&RuntimeHooksDelegate::HandleSendNativeMessage, kSendNativeMessage},
}; };
ScriptContext* script_context = ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
ScriptContextSet::GetContextByV8Context(context);
DCHECK(script_context);
Handler handler = nullptr; Handler handler = nullptr;
for (const auto& handler_entry : kHandlers) { for (const auto& handler_entry : kHandlers) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment