| // Copyright 2015 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 "components/dom_distiller/content/renderer/distiller_native_javascript.h" |
| |
| #include <string> |
| |
| #include "base/bind.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "components/dom_distiller/content/common/distiller_javascript_service.mojom.h" |
| #include "content/public/renderer/render_frame.h" |
| #include "gin/arguments.h" |
| #include "gin/function_template.h" |
| #include "services/service_manager/public/cpp/interface_provider.h" |
| #include "third_party/blink/public/web/blink.h" |
| #include "v8/include/v8.h" |
| |
| namespace dom_distiller { |
| |
| DistillerNativeJavaScript::DistillerNativeJavaScript( |
| content::RenderFrame* render_frame) |
| : render_frame_(render_frame) {} |
| |
| DistillerNativeJavaScript::~DistillerNativeJavaScript() {} |
| |
| void DistillerNativeJavaScript::AddJavaScriptObjectToFrame( |
| v8::Local<v8::Context> context) { |
| v8::Isolate* isolate = blink::MainThreadIsolate(); |
| v8::HandleScope handle_scope(isolate); |
| if (context.IsEmpty()) |
| return; |
| |
| v8::Context::Scope context_scope(context); |
| |
| v8::Local<v8::Object> distiller_obj = |
| GetOrCreateDistillerObject(isolate, context); |
| |
| EnsureServiceConnected(); |
| |
| // Many functions can simply call the Mojo interface directly and have no |
| // wrapper function for binding. Note that calling distiller_js_service.get() |
| // does not transfer ownership of the interface. |
| BindFunctionToObject( |
| isolate, distiller_obj, "openSettings", |
| base::Bind( |
| &mojom::DistillerJavaScriptService::HandleDistillerOpenSettingsCall, |
| base::Unretained(distiller_js_service_.get()))); |
| } |
| |
| template <typename Sig> |
| void DistillerNativeJavaScript::BindFunctionToObject( |
| v8::Isolate* isolate, |
| v8::Local<v8::Object> javascript_object, |
| const std::string& name, |
| const base::Callback<Sig> callback) { |
| v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| // Get the isolate associated with this object. |
| javascript_object |
| ->Set(context, gin::StringToSymbol(isolate, name), |
| gin::CreateFunctionTemplate(isolate, callback) |
| ->GetFunction(context) |
| .ToLocalChecked()) |
| .Check(); |
| } |
| |
| void DistillerNativeJavaScript::EnsureServiceConnected() { |
| if (!distiller_js_service_ || !distiller_js_service_.is_bound()) { |
| render_frame_->GetRemoteInterfaces()->GetInterface(&distiller_js_service_); |
| } |
| } |
| |
| v8::Local<v8::Object> GetOrCreateDistillerObject( |
| v8::Isolate* isolate, |
| v8::Local<v8::Context> context) { |
| v8::Local<v8::Object> global = context->Global(); |
| v8::Local<v8::Object> distiller_obj; |
| v8::Local<v8::Value> distiller_value; |
| if (!global->Get(context, gin::StringToV8(isolate, "distiller")) |
| .ToLocal(&distiller_value) || |
| !distiller_value->IsObject()) { |
| distiller_obj = v8::Object::New(isolate); |
| global |
| ->Set(context, gin::StringToSymbol(isolate, "distiller"), distiller_obj) |
| .Check(); |
| } else { |
| distiller_obj = v8::Local<v8::Object>::Cast(distiller_value); |
| } |
| return distiller_obj; |
| } |
| |
| } // namespace dom_distiller |