blob: 379776d4088c8765fd080565b03995b1bb6e34b5 [file] [log] [blame]
// 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