blob: c70d24641b49203ce77464e107b6e9ffe18dd8c1 [file] [log] [blame]
Devlin Croninedf9d952018-02-07 17:59:491// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "extensions/renderer/i18n_hooks_delegate.h"
6
Avi Drissman197295ae2018-12-25 20:28:347#include "base/stl_util.h"
Devlin Croninedf9d952018-02-07 17:59:498#include "content/public/renderer/render_frame.h"
9#include "content/public/renderer/render_thread.h"
10#include "extensions/common/extension.h"
11#include "extensions/renderer/bindings/api_signature.h"
12#include "extensions/renderer/bindings/js_runner.h"
13#include "extensions/renderer/get_script_context.h"
14#include "extensions/renderer/i18n_hooks_util.h"
15#include "extensions/renderer/script_context.h"
16#include "gin/converter.h"
17
18namespace extensions {
19
20namespace {
21
22constexpr char kGetMessage[] = "i18n.getMessage";
23constexpr char kGetUILanguage[] = "i18n.getUILanguage";
24constexpr char kDetectLanguage[] = "i18n.detectLanguage";
25
26} // namespace
27
28using RequestResult = APIBindingHooks::RequestResult;
29
30I18nHooksDelegate::I18nHooksDelegate() {}
31I18nHooksDelegate::~I18nHooksDelegate() = default;
32
33RequestResult I18nHooksDelegate::HandleRequest(
34 const std::string& method_name,
35 const APISignature* signature,
36 v8::Local<v8::Context> context,
37 std::vector<v8::Local<v8::Value>>* arguments,
38 const APITypeReferenceMap& refs) {
39 using Handler = RequestResult (I18nHooksDelegate::*)(
40 ScriptContext*, const std::vector<v8::Local<v8::Value>>&);
41 static const struct {
42 Handler handler;
43 base::StringPiece method;
44 } kHandlers[] = {
45 {&I18nHooksDelegate::HandleGetMessage, kGetMessage},
46 {&I18nHooksDelegate::HandleGetUILanguage, kGetUILanguage},
47 {&I18nHooksDelegate::HandleDetectLanguage, kDetectLanguage},
48 };
49
50 ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
51
52 Handler handler = nullptr;
53 for (const auto& handler_entry : kHandlers) {
54 if (handler_entry.method == method_name) {
55 handler = handler_entry.handler;
56 break;
57 }
58 }
59
60 if (!handler)
61 return RequestResult(RequestResult::NOT_HANDLED);
62
63 std::string error;
64 std::vector<v8::Local<v8::Value>> parsed_arguments;
65 if (!signature->ParseArgumentsToV8(context, *arguments, refs,
66 &parsed_arguments, &error)) {
67 RequestResult result(RequestResult::INVALID_INVOCATION);
68 result.error = std::move(error);
69 return result;
70 }
71
72 return (this->*handler)(script_context, parsed_arguments);
73}
74
75RequestResult I18nHooksDelegate::HandleGetMessage(
76 ScriptContext* script_context,
77 const std::vector<v8::Local<v8::Value>>& parsed_arguments) {
78 DCHECK(script_context->extension());
79 DCHECK(parsed_arguments[0]->IsString());
80 v8::Local<v8::Value> message = i18n_hooks::GetI18nMessage(
Dan Elphick38a508052018-07-23 22:19:5381 gin::V8ToString(script_context->isolate(), parsed_arguments[0]),
82 script_context->extension()->id(), parsed_arguments[1],
83 script_context->GetRenderFrame(), script_context->v8_context());
Devlin Croninedf9d952018-02-07 17:59:4984
85 RequestResult result(RequestResult::HANDLED);
86 result.return_value = message;
87 return result;
88}
89
90RequestResult I18nHooksDelegate::HandleGetUILanguage(
91 ScriptContext* script_context,
92 const std::vector<v8::Local<v8::Value>>& parsed_arguments) {
93 RequestResult result(RequestResult::HANDLED);
94 result.return_value = gin::StringToSymbol(
95 script_context->isolate(), content::RenderThread::Get()->GetLocale());
96 return result;
97}
98
99RequestResult I18nHooksDelegate::HandleDetectLanguage(
100 ScriptContext* script_context,
101 const std::vector<v8::Local<v8::Value>>& parsed_arguments) {
102 DCHECK(parsed_arguments[0]->IsString());
103 DCHECK(parsed_arguments[1]->IsFunction());
104
105 v8::Local<v8::Context> v8_context = script_context->v8_context();
106
107 v8::Local<v8::Value> detected_languages = i18n_hooks::DetectTextLanguage(
Dan Elphick38a508052018-07-23 22:19:53108 v8_context,
109 gin::V8ToString(script_context->isolate(), parsed_arguments[0]));
Devlin Croninedf9d952018-02-07 17:59:49110
111 // NOTE(devlin): The JS bindings make this callback asynchronous through a
112 // setTimeout, but it shouldn't be necessary.
113 v8::Local<v8::Value> callback_args[] = {detected_languages};
114 JSRunner::Get(v8_context)
115 ->RunJSFunction(parsed_arguments[1].As<v8::Function>(),
Avi Drissman197295ae2018-12-25 20:28:34116 script_context->v8_context(), base::size(callback_args),
Devlin Croninedf9d952018-02-07 17:59:49117 callback_args);
118
119 return RequestResult(RequestResult::HANDLED);
120}
121
122} // namespace extensions