blob: 096197ae6bad4f85d195608a565ceedaae50d763 [file] [log] [blame]
// Copyright 2019 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 "chrome/renderer/extensions/accessibility_private_hooks_delegate.h"
#include "base/i18n/unicodestring.h"
#include "base/strings/utf_string_conversions.h"
#include "extensions/common/extension.h"
#include "extensions/renderer/bindings/api_signature.h"
#include "extensions/renderer/get_script_context.h"
#include "extensions/renderer/script_context.h"
#include "gin/converter.h"
#include "third_party/icu/source/common/unicode/locid.h"
namespace extensions {
namespace {
constexpr char kGetDisplayLanguage[] =
"accessibilityPrivate.getDisplayLanguage";
constexpr char kUndeterminedLanguage[] = "und";
} // namespace
using RequestResult = APIBindingHooks::RequestResult;
AccessibilityPrivateHooksDelegate::AccessibilityPrivateHooksDelegate() =
default;
AccessibilityPrivateHooksDelegate::~AccessibilityPrivateHooksDelegate() =
default;
RequestResult AccessibilityPrivateHooksDelegate::HandleRequest(
const std::string& method_name,
const APISignature* signature,
v8::Local<v8::Context> context,
std::vector<v8::Local<v8::Value>>* arguments,
const APITypeReferenceMap& refs) {
// Error checks.
// Ensure we would like to call the GetDisplayLanguage function.
if (method_name != kGetDisplayLanguage)
return RequestResult(RequestResult::NOT_HANDLED);
// Ensure arguments are successfully parsed and converted.
APISignature::V8ParseResult parse_result =
signature->ParseArgumentsToV8(context, *arguments, refs);
if (!parse_result.succeeded()) {
RequestResult result(RequestResult::INVALID_INVOCATION);
result.error = std::move(*parse_result.error);
return result;
}
return HandleGetDisplayLanguage(GetScriptContextFromV8ContextChecked(context),
*parse_result.arguments);
}
// Called to translate |language_code_to_translate| into human-readable string
// in the language specified by |target_language_code|. For example, if
// language_code_to_translate = 'en' and target_language_code = 'fr', then this
// function returns 'anglais'.
// If language_code_to_translate = 'fr' and target_language_code = 'en', then
// this function returns 'french'.
RequestResult AccessibilityPrivateHooksDelegate::HandleGetDisplayLanguage(
ScriptContext* script_context,
const std::vector<v8::Local<v8::Value>>& parsed_arguments) {
DCHECK(script_context->extension());
DCHECK_EQ(2u, parsed_arguments.size());
DCHECK(parsed_arguments[0]->IsString());
DCHECK(parsed_arguments[1]->IsString());
std::string language_code_to_translate =
gin::V8ToString(script_context->isolate(), parsed_arguments[0]);
std::string target_language_code =
gin::V8ToString(script_context->isolate(), parsed_arguments[1]);
// The locale whose language code we want to translate.
icu::Locale locale_to_translate =
icu::Locale(language_code_to_translate.c_str());
// The locale that |display_language| should be in.
icu::Locale target_locale = icu::Locale(target_language_code.c_str());
// Validate locales.
// Get list of available locales. Please see the ICU User Guide for more
// details: http://userguide.icu-project.org/locale.
bool valid_arg1 = false;
bool valid_arg2 = false;
int32_t num_locales = 0;
const icu::Locale* available_locales =
icu::Locale::getAvailableLocales(num_locales);
for (int32_t i = 0; i < num_locales; ++i) {
// Check both the language and country for each locale.
const char* current_language = available_locales[i].getLanguage();
const char* current_country = available_locales[i].getCountry();
if (strcmp(locale_to_translate.getLanguage(), current_language) == 0 &&
strcmp(locale_to_translate.getCountry(), current_country) == 0) {
valid_arg1 = true;
}
if (strcmp(target_locale.getLanguage(), current_language) == 0 &&
strcmp(target_locale.getCountry(), current_country) == 0) {
valid_arg2 = true;
}
}
// If either of the language codes is invalid, we should return empty string.
if (!(valid_arg1 && valid_arg2)) {
RequestResult empty_result(RequestResult::HANDLED);
empty_result.return_value = gin::StringToV8(script_context->isolate(), "");
return empty_result;
}
icu::UnicodeString display_language;
locale_to_translate.getDisplayLanguage(target_locale, display_language);
std::string language_result =
base::UTF16ToUTF8(base::i18n::UnicodeStringToString16(display_language));
// Instead of returning "und", which is what the ICU Locale class returns for
// undetermined languages, we would simply like to return an empty string
// to communicate that we could not determine the display language.
if (language_result == kUndeterminedLanguage)
language_result = "";
RequestResult result(RequestResult::HANDLED);
result.return_value =
gin::StringToV8(script_context->isolate(), language_result);
return result;
}
} // namespace extensions