Index: extensions/renderer/native_extension_bindings_system.cc |
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc |
index 0669c14dc3e52108856cc791769a6304f4a7f371..a67b01180d520099d04c81c1afe94ce949da339d 100644 |
--- a/extensions/renderer/native_extension_bindings_system.cc |
+++ b/extensions/renderer/native_extension_bindings_system.cc |
@@ -81,6 +81,52 @@ void CallJsFunction(v8::Local<v8::Function> function, |
script_context->SafeCallFunction(function, argc, argv); |
} |
+// A helper class for calling JS function synchronously. |
+class CallJsSyncHelper { |
+ public: |
+ CallJsSyncHelper(v8::Isolate* isolate) : isolate_(isolate), |
+ weak_factory_(this) {} |
+ ~CallJsSyncHelper() {} |
+ |
+ ScriptInjectionCallback::CompleteCallback GetCallback() { |
+ return base::Bind(&CallJsSyncHelper::OnJsComplete, |
+ weak_factory_.GetWeakPtr()); |
+ } |
+ |
+ bool did_complete() const { return did_complete_; } |
+ v8::Global<v8::Value> take_result() { return std::move(result_); } |
+ |
+ private: |
+ void OnJsComplete(const std::vector<v8::Local<v8::Value>>& results) { |
+ DCHECK_EQ(1u, results.size()); |
+ did_complete_ = true; |
+ // The locals are released after the callback is executed, so we need to |
+ // grab a persistent handle. |
+ result_.Reset(isolate_, results[0]); |
+ } |
+ |
+ bool did_complete_ = false; |
+ v8::Isolate* isolate_; |
+ v8::Global<v8::Value> result_; |
+ base::WeakPtrFactory<CallJsSyncHelper> weak_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CallJsSyncHelper); |
+}; |
+ |
+v8::Global<v8::Value> CallJsFunctionSync(v8::Local<v8::Function> function, |
+ v8::Local<v8::Context> context, |
+ int argc, |
+ v8::Local<v8::Value> argv[]) { |
+ CallJsSyncHelper helper(context->GetIsolate()); |
+ ScriptContext* script_context = |
+ ScriptContextSet::GetContextByV8Context(context); |
+ CHECK(script_context); |
+ script_context->SafeCallFunction(function, argc, argv, helper.GetCallback()); |
+ // If the JS did not, in fact, execute synchronously, there's a big problem. |
+ CHECK(helper.did_complete()); |
+ return helper.take_result(); |
+} |
+ |
// Returns the API schema indicated by |api_name|. |
const base::DictionaryValue& GetAPISchema(const std::string& api_name) { |
const base::DictionaryValue* schema = |
@@ -102,6 +148,7 @@ NativeExtensionBindingsSystem::NativeExtensionBindingsSystem( |
const SendIPCMethod& send_ipc) |
: send_ipc_(send_ipc), |
api_system_(base::Bind(&CallJsFunction), |
+ base::Bind(&CallJsFunctionSync), |
base::Bind(&GetAPISchema), |
base::Bind(&NativeExtensionBindingsSystem::SendRequest, |
base::Unretained(this))), |