Commit bdf15246 authored by Steven Bennetts's avatar Steven Bennetts Committed by Commit Bot

Support compressed .json grit files, compress chromevox msgs (Take 3)

This provides support for type="chrome_messages_json_gzip" in
grit/build.py, which compresses the output files (which should have
.gz appended to the name, e.g. messages.json.gz).

This makes it fairly simple to convert an extension (e.g. chromevox)
to use compressed l10n files.

Original CL:
https://chromium-review.googlesource.com/c/chromium/src/+/1913610

For changes reviewed in the original CL:
TBR=agrieve@chromium.org
TBR=dtseng@chromium.org
TBR=rdevlin.cronin@chromium.org

Bug: 1023568
Change-Id: I7f83e5de8e339aea2e47b84f3ec701350246b38d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1947386Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Commit-Queue: Steven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720779}
parent e8996ed9
...@@ -398,7 +398,7 @@ if (is_chromeos) { ...@@ -398,7 +398,7 @@ if (is_chromeos) {
action("chromevox_test_messages_js") { action("chromevox_test_messages_js") {
script = "tools/generate_test_messages.py" script = "tools/generate_test_messages.py"
sources = [ sources = [
"$chromevox_out_dir/_locales/en/messages.json", "$chromevox_out_dir/_locales/en/messages.json.gz",
] ]
output_file = "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/host/testing/test_messages.js" output_file = "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/host/testing/test_messages.js"
outputs = [ outputs = [
......
...@@ -28,6 +28,7 @@ ChromeVoxLanguageSwitchingTest.prototype = { ...@@ -28,6 +28,7 @@ ChromeVoxLanguageSwitchingTest.prototype = {
#include "base/callback.h" #include "base/callback.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/extension_constants.h"
#include "extensions/common/extension_l10n_util.h"
// The following includes are necessary for this test file. // The following includes are necessary for this test file.
#include "base/command_line.h" #include "base/command_line.h"
...@@ -48,6 +49,7 @@ ChromeVoxLanguageSwitchingTest.prototype = { ...@@ -48,6 +49,7 @@ ChromeVoxLanguageSwitchingTest.prototype = {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(::switches::kLang, "en-US"); base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(::switches::kLang, "en-US");
// Copy-pasted from chromevox_e2e_test_base.js. // Copy-pasted from chromevox_e2e_test_base.js.
auto allow = extension_l10n_util::AllowGzippedMessagesAllowedForTest();
base::Closure load_cb = base::Closure load_cb =
base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback, base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback,
base::Unretained(chromeos::AccessibilityManager::Get()), base::Unretained(chromeos::AccessibilityManager::Get()),
......
...@@ -10,59 +10,59 @@ template("chromevox_strings") { ...@@ -10,59 +10,59 @@ template("chromevox_strings") {
source = "//chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd" source = "//chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd"
defines = chrome_grit_defines defines = chrome_grit_defines
outputs = [ outputs = [
"_locales/am/messages.json", "_locales/am/messages.json.gz",
"_locales/ar/messages.json", "_locales/ar/messages.json.gz",
"_locales/bg/messages.json", "_locales/bg/messages.json.gz",
"_locales/bn/messages.json", "_locales/bn/messages.json.gz",
"_locales/ca/messages.json", "_locales/ca/messages.json.gz",
"_locales/cs/messages.json", "_locales/cs/messages.json.gz",
"_locales/da/messages.json", "_locales/da/messages.json.gz",
"_locales/de/messages.json", "_locales/de/messages.json.gz",
"_locales/el/messages.json", "_locales/el/messages.json.gz",
"_locales/en_GB/messages.json", "_locales/en_GB/messages.json.gz",
"_locales/en/messages.json", "_locales/en/messages.json.gz",
"_locales/es/messages.json", "_locales/es/messages.json.gz",
"_locales/es_419/messages.json", "_locales/es_419/messages.json.gz",
"_locales/et/messages.json", "_locales/et/messages.json.gz",
"_locales/fa/messages.json", "_locales/fa/messages.json.gz",
"_locales/fi/messages.json", "_locales/fi/messages.json.gz",
"_locales/fil/messages.json", "_locales/fil/messages.json.gz",
"_locales/fr/messages.json", "_locales/fr/messages.json.gz",
"_locales/gu/messages.json", "_locales/gu/messages.json.gz",
"_locales/he/messages.json", "_locales/he/messages.json.gz",
"_locales/hi/messages.json", "_locales/hi/messages.json.gz",
"_locales/hr/messages.json", "_locales/hr/messages.json.gz",
"_locales/hu/messages.json", "_locales/hu/messages.json.gz",
"_locales/id/messages.json", "_locales/id/messages.json.gz",
"_locales/it/messages.json", "_locales/it/messages.json.gz",
"_locales/ja/messages.json", "_locales/ja/messages.json.gz",
"_locales/kn/messages.json", "_locales/kn/messages.json.gz",
"_locales/ko/messages.json", "_locales/ko/messages.json.gz",
"_locales/lt/messages.json", "_locales/lt/messages.json.gz",
"_locales/lv/messages.json", "_locales/lv/messages.json.gz",
"_locales/ml/messages.json", "_locales/ml/messages.json.gz",
"_locales/mr/messages.json", "_locales/mr/messages.json.gz",
"_locales/ms/messages.json", "_locales/ms/messages.json.gz",
"_locales/nl/messages.json", "_locales/nl/messages.json.gz",
"_locales/nb/messages.json", "_locales/nb/messages.json.gz",
"_locales/pl/messages.json", "_locales/pl/messages.json.gz",
"_locales/pt_BR/messages.json", "_locales/pt_BR/messages.json.gz",
"_locales/pt_PT/messages.json", "_locales/pt_PT/messages.json.gz",
"_locales/ro/messages.json", "_locales/ro/messages.json.gz",
"_locales/ru/messages.json", "_locales/ru/messages.json.gz",
"_locales/sk/messages.json", "_locales/sk/messages.json.gz",
"_locales/sl/messages.json", "_locales/sl/messages.json.gz",
"_locales/sr/messages.json", "_locales/sr/messages.json.gz",
"_locales/sv/messages.json", "_locales/sv/messages.json.gz",
"_locales/sw/messages.json", "_locales/sw/messages.json.gz",
"_locales/ta/messages.json", "_locales/ta/messages.json.gz",
"_locales/te/messages.json", "_locales/te/messages.json.gz",
"_locales/th/messages.json", "_locales/th/messages.json.gz",
"_locales/tr/messages.json", "_locales/tr/messages.json.gz",
"_locales/uk/messages.json", "_locales/uk/messages.json.gz",
"_locales/vi/messages.json", "_locales/vi/messages.json.gz",
"_locales/zh_CN/messages.json", "_locales/zh_CN/messages.json.gz",
"_locales/zh_TW/messages.json", "_locales/zh_TW/messages.json.gz",
] ]
output_dir = invoker.out_dir output_dir = invoker.out_dir
......
...@@ -39,12 +39,14 @@ ChromeVoxE2ETest.prototype = { ...@@ -39,12 +39,14 @@ ChromeVoxE2ETest.prototype = {
#include "base/callback.h" #include "base/callback.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/extension_constants.h"
#include "extensions/common/extension_l10n_util.h"
`); `);
}, },
/** @override */ /** @override */
testGenPreamble: function() { testGenPreamble: function() {
GEN(` GEN(`
auto allow = extension_l10n_util::AllowGzippedMessagesAllowedForTest();
base::Closure load_cb = base::Closure load_cb =
base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback, base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback,
base::Unretained(chromeos::AccessibilityManager::Get()), base::Unretained(chromeos::AccessibilityManager::Get()),
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
# found in the LICENSE file. # found in the LICENSE file.
'''Generates test_messages.js from an extension message json file.''' '''Generates test_messages.js from an extension message json file.'''
import gzip
import optparse import optparse
import sys import sys
...@@ -38,7 +39,11 @@ def main(): ...@@ -38,7 +39,11 @@ def main():
if len(args) != 1: if len(args) != 1:
Die('Exactly one input file must be specified') Die('Exactly one input file must be specified')
in_file_name = args[0] in_file_name = args[0]
with open(in_file_name) as in_file: def _OpenFile(filename):
if filename.endswith('.gz'):
return gzip.open(filename)
return open(filename)
with _OpenFile(in_file_name) as in_file:
json = in_file.read().strip() json = in_file.read().strip()
with open(options.output_file, 'w') as out_file: with open(options.output_file, 'w') as out_file:
out_file.write(_JS_TEMPLATE % {'in_file': in_file_name, 'json': json}) out_file.write(_JS_TEMPLATE % {'in_file': in_file_name, 'json': json})
......
...@@ -36,6 +36,8 @@ namespace keys = extensions::manifest_keys; ...@@ -36,6 +36,8 @@ namespace keys = extensions::manifest_keys;
namespace { namespace {
bool g_allow_gzipped_messages_for_test = false;
// Loads contents of the messages file for given locale. If file is not found, // Loads contents of the messages file for given locale. If file is not found,
// or there was parsing error we return null and set |error|. If // or there was parsing error we return null and set |error|. If
// |gzip_permission| is kAllowForTrustedSource, this will also look for a .gz // |gzip_permission| is kAllowForTrustedSource, this will also look for a .gz
...@@ -54,7 +56,8 @@ std::unique_ptr<base::DictionaryValue> LoadMessageFile( ...@@ -54,7 +56,8 @@ std::unique_ptr<base::DictionaryValue> LoadMessageFile(
dictionary = base::DictionaryValue::From( dictionary = base::DictionaryValue::From(
messages_deserializer.Deserialize(nullptr, error)); messages_deserializer.Deserialize(nullptr, error));
} else if (gzip_permission == extension_l10n_util::GzippedMessagesPermission:: } else if (gzip_permission == extension_l10n_util::GzippedMessagesPermission::
kAllowForTrustedSource) { kAllowForTrustedSource ||
g_allow_gzipped_messages_for_test) {
// If a compressed version of the file exists, load that. // If a compressed version of the file exists, load that.
base::FilePath compressed_file_path = base::FilePath compressed_file_path =
file_path.AddExtension(FILE_PATH_LITERAL(".gz")); file_path.AddExtension(FILE_PATH_LITERAL(".gz"));
...@@ -75,6 +78,8 @@ std::unique_ptr<base::DictionaryValue> LoadMessageFile( ...@@ -75,6 +78,8 @@ std::unique_ptr<base::DictionaryValue> LoadMessageFile(
dictionary = base::DictionaryValue::From( dictionary = base::DictionaryValue::From(
messages_deserializer.Deserialize(nullptr, error)); messages_deserializer.Deserialize(nullptr, error));
} }
} else {
LOG(ERROR) << "Unable to load message file: " << locale_path.AsUTF8Unsafe();
} }
if (!dictionary) { if (!dictionary) {
...@@ -154,6 +159,10 @@ std::string LocaleForLocalization() { ...@@ -154,6 +159,10 @@ std::string LocaleForLocalization() {
namespace extension_l10n_util { namespace extension_l10n_util {
base::AutoReset<bool> AllowGzippedMessagesAllowedForTest() {
return base::AutoReset<bool>(&g_allow_gzipped_messages_for_test, true);
}
void SetProcessLocale(const std::string& locale) { void SetProcessLocale(const std::string& locale) {
GetProcessLocale() = locale; GetProcessLocale() = locale;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/auto_reset.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
namespace base { namespace base {
...@@ -32,6 +33,10 @@ enum class GzippedMessagesPermission { ...@@ -32,6 +33,10 @@ enum class GzippedMessagesPermission {
kAllowForTrustedSource, kAllowForTrustedSource,
}; };
// Called from tests to temporarily allow loading gzipped messages for non
// component test extensions.
base::AutoReset<bool> AllowGzippedMessagesAllowedForTest();
// Set the locale for this process to a fixed value, rather than using the // Set the locale for this process to a fixed value, rather than using the
// normal file-based lookup mechanisms. This is used to set the locale inside // normal file-based lookup mechanisms. This is used to set the locale inside
// the sandboxed utility process, where file reading is not allowed. // the sandboxed utility process, where file reading is not allowed.
......
...@@ -10,6 +10,7 @@ from __future__ import print_function ...@@ -10,6 +10,7 @@ from __future__ import print_function
import codecs import codecs
import filecmp import filecmp
import getopt import getopt
import gzip
import os import os
import shutil import shutil
import sys import sys
...@@ -34,6 +35,7 @@ _format_modules = { ...@@ -34,6 +35,7 @@ _format_modules = {
'android': 'android_xml', 'android': 'android_xml',
'c_format': 'c_format', 'c_format': 'c_format',
'chrome_messages_json': 'chrome_messages_json', 'chrome_messages_json': 'chrome_messages_json',
'chrome_messages_json_gzip': 'chrome_messages_json',
'data_package': 'data_pack', 'data_package': 'data_pack',
'policy_templates': 'policy_templates_json', 'policy_templates': 'policy_templates_json',
'rc_all': 'rc', 'rc_all': 'rc',
...@@ -359,7 +361,7 @@ are exported to translation interchange files (e.g. XMB files), etc. ...@@ -359,7 +361,7 @@ are exported to translation interchange files (e.g. XMB files), etc.
return 'cp1252' return 'cp1252'
if output_type in ('android', 'c_format', 'plist', 'plist_strings', 'doc', if output_type in ('android', 'c_format', 'plist', 'plist_strings', 'doc',
'json', 'android_policy', 'chrome_messages_json', 'json', 'android_policy', 'chrome_messages_json',
'policy_templates'): 'chrome_messages_json_gzip', 'policy_templates'):
return 'utf_8' return 'utf_8'
# TODO(gfeher) modify here to set utf-8 encoding for admx/adml # TODO(gfeher) modify here to set utf-8 encoding for admx/adml
return 'utf_16' return 'utf_16'
...@@ -392,24 +394,34 @@ are exported to translation interchange files (e.g. XMB files), etc. ...@@ -392,24 +394,34 @@ are exported to translation interchange files (e.g. XMB files), etc.
# Write the results to a temporary file and only overwrite the original # Write the results to a temporary file and only overwrite the original
# if the file changed. This avoids unnecessary rebuilds. # if the file changed. This avoids unnecessary rebuilds.
outfile = self.fo_create(output.GetOutputFilename() + '.tmp', 'wb') out_filename = output.GetOutputFilename()
tmp_filename = out_filename + '.tmp'
tmpfile = self.fo_create(tmp_filename, 'wb')
if output.GetType() != 'data_package': output_type = output.GetType()
encoding = self._EncodingForOutputType(output.GetType()) if output_type != 'data_package':
outfile = util.WrapOutputStream(outfile, encoding) encoding = self._EncodingForOutputType(output_type)
tmpfile = util.WrapOutputStream(tmpfile, encoding)
# Iterate in-order through entire resource tree, calling formatters on # Iterate in-order through entire resource tree, calling formatters on
# the entry into a node and on exit out of it. # the entry into a node and on exit out of it.
with outfile: with tmpfile:
self.ProcessNode(self.res, output, outfile) self.ProcessNode(self.res, output, tmpfile)
if output_type == 'chrome_messages_json_gzip':
gz_filename = tmp_filename + '.gz'
with open(tmp_filename, 'rb') as tmpfile, open(gz_filename, 'wb') as f:
with gzip.GzipFile(filename='', mode='wb', fileobj=f, mtime=0) as fgz:
shutil.copyfileobj(tmpfile, fgz)
os.remove(tmp_filename)
tmp_filename = gz_filename
# Now copy from the temp file back to the real output, but on Windows, # Now copy from the temp file back to the real output, but on Windows,
# only if the real output doesn't exist or the contents of the file # only if the real output doesn't exist or the contents of the file
# changed. This prevents identical headers from being written and .cc # changed. This prevents identical headers from being written and .cc
# files from recompiling (which is painful on Windows). # files from recompiling (which is painful on Windows).
if not os.path.exists(output.GetOutputFilename()): if not os.path.exists(out_filename):
os.rename(output.GetOutputFilename() + '.tmp', os.rename(tmp_filename, out_filename)
output.GetOutputFilename())
else: else:
# CHROMIUM SPECIFIC CHANGE. # CHROMIUM SPECIFIC CHANGE.
# This clashes with gyp + vstudio, which expect the output timestamp # This clashes with gyp + vstudio, which expect the output timestamp
...@@ -418,13 +430,11 @@ are exported to translation interchange files (e.g. XMB files), etc. ...@@ -418,13 +430,11 @@ are exported to translation interchange files (e.g. XMB files), etc.
if not self.write_only_new: if not self.write_only_new:
write_file = True write_file = True
else: else:
files_match = filecmp.cmp(output.GetOutputFilename(), files_match = filecmp.cmp(out_filename, tmp_filename)
output.GetOutputFilename() + '.tmp')
write_file = not files_match write_file = not files_match
if write_file: if write_file:
shutil.copy2(output.GetOutputFilename() + '.tmp', shutil.copy2(tmp_filename, out_filename)
output.GetOutputFilename()) os.remove(tmp_filename)
os.remove(output.GetOutputFilename() + '.tmp')
self.VerboseOut(' done.\n') self.VerboseOut(' done.\n')
......
...@@ -480,7 +480,8 @@ template("grit") { ...@@ -480,7 +480,8 @@ template("grit") {
sources = [] sources = []
foreach(output, grit_outputs) { foreach(output, grit_outputs) {
extension = get_path_info(output, "extension") extension = get_path_info(output, "extension")
if (extension != "json" && extension != "pak" && extension != "xml") { if (extension != "json" && extension != "gz" && extension != "pak" &&
extension != "xml") {
sources += [ output ] sources += [ output ]
} }
} }
......
...@@ -459,7 +459,7 @@ chromevox_strings("chromevox_strings") { ...@@ -459,7 +459,7 @@ chromevox_strings("chromevox_strings") {
action("chromevox_test_messages_js") { action("chromevox_test_messages_js") {
script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_test_messages.py" script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_test_messages.py"
sources = [ sources = [
"$chromevox_out_dir/_locales/en/messages.json", "$chromevox_out_dir/_locales/en/messages.json.gz",
] ]
output_file = "$root_out_dir/test_data/ui/accessibility/extensions/chromevoxclassic/host/testing/test_messages.js" output_file = "$root_out_dir/test_data/ui/accessibility/extensions/chromevoxclassic/host/testing/test_messages.js"
outputs = [ outputs = [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment