summaryrefslogtreecommitdiff
path: root/chromium/extensions/common/manifest_handlers/default_locale_handler.cc
blob: 83dfdc71f7e94257e86dc550e6c3e241bc29d208 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (c) 2013 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 "extensions/common/manifest_handlers/default_locale_handler.h"

#include <memory>

#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_l10n_util.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/strings/grit/extensions_strings.h"
#include "ui/base/l10n/l10n_util.h"

namespace extensions {

namespace keys = manifest_keys;
namespace errors = manifest_errors;

// static
const std::string& LocaleInfo::GetDefaultLocale(const Extension* extension) {
  LocaleInfo* info = static_cast<LocaleInfo*>(
      extension->GetManifestData(keys::kDefaultLocale));
  return info ? info->default_locale : base::EmptyString();
}

DefaultLocaleHandler::DefaultLocaleHandler() {
}

DefaultLocaleHandler::~DefaultLocaleHandler() {
}

bool DefaultLocaleHandler::Parse(Extension* extension, base::string16* error) {
  std::unique_ptr<LocaleInfo> info(new LocaleInfo);
  if (!extension->manifest()->GetString(keys::kDefaultLocale,
                                        &info->default_locale) ||
      !l10n_util::IsValidLocaleSyntax(info->default_locale)) {
    *error = base::ASCIIToUTF16(manifest_errors::kInvalidDefaultLocale);
    return false;
  }
  extension->SetManifestData(keys::kDefaultLocale, std::move(info));
  return true;
}

bool DefaultLocaleHandler::Validate(
    const Extension* extension,
    std::string* error,
    std::vector<InstallWarning>* warnings) const {
  // default_locale and _locales have to be both present or both missing.
  const base::FilePath path = extension->path().Append(kLocaleFolder);
  bool path_exists = base::PathExists(path);
  std::string default_locale =
      extensions::LocaleInfo::GetDefaultLocale(extension);

  // If both default locale and _locales folder are empty, skip verification.
  if (default_locale.empty() && !path_exists)
    return true;

  if (default_locale.empty() && path_exists) {
    *error = l10n_util::GetStringUTF8(
        IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED);
    return false;
  } else if (!default_locale.empty() && !path_exists) {
    *error = errors::kLocalesTreeMissing;
    return false;
  }

  // Treat all folders under _locales as valid locales.
  base::FileEnumerator locales(path, false, base::FileEnumerator::DIRECTORIES);

  std::set<std::string> all_locales;
  extension_l10n_util::GetAllLocales(&all_locales);
  const base::FilePath default_locale_path = path.AppendASCII(default_locale);
  bool has_default_locale_message_file = false;

  base::FilePath locale_path;
  while (!(locale_path = locales.Next()).empty()) {
    if (extension_l10n_util::ShouldSkipValidation(path, locale_path,
                                                  all_locales))
      continue;

    base::FilePath messages_path = locale_path.Append(kMessagesFilename);

    if (!base::PathExists(messages_path)) {
      *error = base::StringPrintf(
          "%s %s", errors::kLocalesMessagesFileMissing,
          base::UTF16ToUTF8(messages_path.LossyDisplayName()).c_str());
      return false;
    }

    if (locale_path == default_locale_path)
      has_default_locale_message_file = true;
  }

  // Only message file for default locale has to exist.
  if (!has_default_locale_message_file) {
    *error = errors::kLocalesNoDefaultMessages;
    return false;
  }

  return true;
}

bool DefaultLocaleHandler::AlwaysValidateForType(Manifest::Type type) const {
  // Required to validate _locales directory; see Validate.
  return true;
}

base::span<const char* const> DefaultLocaleHandler::Keys() const {
  static constexpr const char* kKeys[] = {keys::kDefaultLocale};
  return kKeys;
}

}  // namespace extensions