1 // Copyright 2019 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 "chrome/renderer/extensions/accessibility_private_hooks_delegate.h"
6 
7 #include "base/i18n/unicodestring.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "extensions/common/extension.h"
10 #include "extensions/renderer/bindings/api_signature.h"
11 #include "extensions/renderer/get_script_context.h"
12 #include "extensions/renderer/script_context.h"
13 #include "gin/converter.h"
14 #include "ui/base/l10n/l10n_util.h"
15 
16 namespace extensions {
17 
18 namespace {
19 constexpr char kGetDisplayNameForLocale[] =
20     "accessibilityPrivate.getDisplayNameForLocale";
21 constexpr char kUndeterminedLocale[] = "und";
22 }  // namespace
23 
24 using RequestResult = APIBindingHooks::RequestResult;
25 
26 AccessibilityPrivateHooksDelegate::AccessibilityPrivateHooksDelegate() =
27     default;
28 AccessibilityPrivateHooksDelegate::~AccessibilityPrivateHooksDelegate() =
29     default;
30 
HandleRequest(const std::string & method_name,const APISignature * signature,v8::Local<v8::Context> context,std::vector<v8::Local<v8::Value>> * arguments,const APITypeReferenceMap & refs)31 RequestResult AccessibilityPrivateHooksDelegate::HandleRequest(
32     const std::string& method_name,
33     const APISignature* signature,
34     v8::Local<v8::Context> context,
35     std::vector<v8::Local<v8::Value>>* arguments,
36     const APITypeReferenceMap& refs) {
37   // Error checks.
38   // Ensure we would like to call the GetDisplayNameForLocale function.
39   if (method_name != kGetDisplayNameForLocale)
40     return RequestResult(RequestResult::NOT_HANDLED);
41   // Ensure arguments are successfully parsed and converted.
42   APISignature::V8ParseResult parse_result =
43       signature->ParseArgumentsToV8(context, *arguments, refs);
44   if (!parse_result.succeeded()) {
45     RequestResult result(RequestResult::INVALID_INVOCATION);
46     result.error = std::move(*parse_result.error);
47     return result;
48   }
49   return HandleGetDisplayNameForLocale(
50       GetScriptContextFromV8ContextChecked(context), *parse_result.arguments);
51 }
52 
HandleGetDisplayNameForLocale(ScriptContext * script_context,const std::vector<v8::Local<v8::Value>> & parsed_arguments)53 RequestResult AccessibilityPrivateHooksDelegate::HandleGetDisplayNameForLocale(
54     ScriptContext* script_context,
55     const std::vector<v8::Local<v8::Value>>& parsed_arguments) {
56   DCHECK(script_context->extension());
57   DCHECK_EQ(2u, parsed_arguments.size());
58   DCHECK(parsed_arguments[0]->IsString());
59   DCHECK(parsed_arguments[1]->IsString());
60 
61   const std::string locale =
62       gin::V8ToString(script_context->isolate(), parsed_arguments[0]);
63   const std::string display_locale =
64       gin::V8ToString(script_context->isolate(), parsed_arguments[1]);
65 
66   bool found_valid_result = false;
67   std::string locale_result;
68   if (l10n_util::IsValidLocaleSyntax(locale) &&
69       l10n_util::IsValidLocaleSyntax(display_locale)) {
70     locale_result = base::UTF16ToUTF8(l10n_util::GetDisplayNameForLocale(
71         locale, display_locale, true /* is_ui */));
72     // Check for valid locales before getting the display name.
73     // The ICU Locale class returns "und" for undetermined locales, and
74     // returns the locale string directly if it has no translation.
75     // Treat these cases as invalid results.
76     found_valid_result =
77         locale_result != kUndeterminedLocale && locale_result != locale;
78   }
79 
80   // We return an empty string to communicate that we could not determine
81   // the display locale.
82   if (!found_valid_result)
83     locale_result = std::string();
84 
85   RequestResult result(RequestResult::HANDLED);
86   result.return_value =
87       gin::StringToV8(script_context->isolate(), locale_result);
88   return result;
89 }
90 
91 }  // namespace extensions
92