Commit 8afa24d8 authored by Nico Weber's avatar Nico Weber Committed by Chromium LUCI CQ

mac: Simplify infoplist_strings_util by using base/ more heavily

Also rename the binary to match the name of the source file.

No behavior change.

Bug: 1147069
Change-Id: I61ffe9e1e1672db4e5f1d954949e196cca7fc701
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2583382Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Commit-Queue: Nico Weber <thakis@chromium.org>
Auto-Submit: Nico Weber <thakis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835691}
parent e9a400c4
...@@ -492,7 +492,7 @@ if (is_win) { ...@@ -492,7 +492,7 @@ if (is_win) {
} }
compiled_action("chrome_app_strings") { compiled_action("chrome_app_strings") {
tool = "//chrome/tools/build/mac:infoplist_strings_tool" tool = "//chrome/tools/build/mac:infoplist_strings_util"
inputs = [] inputs = []
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
executable("infoplist_strings_tool") { executable("infoplist_strings_util") {
configs += [ "//build/config/compiler:wexit_time_destructors" ] configs += [ "//build/config/compiler:wexit_time_destructors" ]
sources = [ "infoplist_strings_util.mm" ] sources = [ "infoplist_strings_util.mm" ]
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
// the GRD files and generate the InfoPlist.strings files needed for // the GRD files and generate the InfoPlist.strings files needed for
// Mac OS X app bundles. // Mac OS X app bundles.
#import <Foundation/Foundation.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
...@@ -17,117 +16,84 @@ ...@@ -17,117 +16,84 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/i18n/icu_util.h" #include "base/i18n/icu_util.h"
#include "base/i18n/message_formatter.h" #include "base/i18n/message_formatter.h"
#include "base/mac/scoped_nsobject.h" #include "base/logging.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/grit/chromium_strings.h" #include "chrome/grit/chromium_strings.h"
#include "ui/base/resource/data_pack.h" #include "ui/base/resource/data_pack.h"
namespace { namespace {
ui::DataPack* LoadResourceDataPack(const char* dir_path, std::unique_ptr<ui::DataPack> LoadResourceDataPack(
const char* branding_strings_name, const char* dir_path,
const char* locale_name) { const char* branding_strings_name,
ui::DataPack* resource_pack = NULL; const std::string& locale_name) {
auto path = base::FilePath(base::StringPrintf(
NSString* resource_path = [NSString stringWithFormat:@"%s/%s_%s.pak", "%s/%s_%s.pak", dir_path, branding_strings_name, locale_name.c_str()));
dir_path, branding_strings_name, locale_name]; path = base::MakeAbsoluteFilePath(path);
if (resource_path) { auto resource_pack = std::make_unique<ui::DataPack>(ui::SCALE_FACTOR_100P);
base::FilePath resources_pak_path([resource_path fileSystemRepresentation]); if (!resource_pack->LoadFromPath(path))
resources_pak_path = base::MakeAbsoluteFilePath(resources_pak_path); resource_pack.reset();
resource_pack = new ui::DataPack(ui::SCALE_FACTOR_100P);
bool success = resource_pack->LoadFromPath(resources_pak_path);
if (!success) {
delete resource_pack;
resource_pack = NULL;
}
}
return resource_pack; return resource_pack;
} }
NSString* LoadStringFromDataPack(ui::DataPack* data_pack, std::string LoadStringFromDataPack(ui::DataPack* data_pack,
const char* data_pack_lang, const std::string& data_pack_lang,
uint32_t resource_id, uint32_t resource_id,
const char* resource_id_str) { const char* resource_id_str) {
NSString* result = nil;
base::StringPiece data; base::StringPiece data;
if (data_pack->GetStringPiece(resource_id, &data)) { CHECK(data_pack->GetStringPiece(resource_id, &data))
// Data pack encodes strings as either UTF8 or UTF16. << "failed to load string " << resource_id_str << " for lang "
if (data_pack->GetTextEncodingType() == ui::DataPack::UTF8) { << data_pack_lang;
result =
[[[NSString alloc] initWithBytes:data.data() // Data pack encodes strings as either UTF8 or UTF16.
length:data.length() if (data_pack->GetTextEncodingType() == ui::DataPack::UTF8)
encoding:NSUTF8StringEncoding] return (std::string)data;
autorelease]; if (data_pack->GetTextEncodingType() == ui::DataPack::UTF16) {
} else if (data_pack->GetTextEncodingType() == ui::DataPack::UTF16) { return base::UTF16ToUTF8(base::string16(
result = reinterpret_cast<const base::char16*>(data.data()), data.length() / 2));
[[[NSString alloc] initWithBytes:data.data()
length:data.length()
encoding:NSUTF16LittleEndianStringEncoding]
autorelease];
} else {
fprintf(stderr, "ERROR: requested string %s from binary data pack\n",
resource_id_str);
exit(1);
}
}
if (!result) {
fprintf(stderr, "ERROR: failed to load string %s for lang %s\n",
resource_id_str, data_pack_lang);
exit(1);
} }
return result;
LOG(FATAL) << "requested string " << resource_id_str
<< " from binary data pack";
return std::string(); // Unreachable.
} }
// Escape quotes, newlines, etc so there are no errors when the strings file // Escape quotes, newlines, etc so there are no errors when the strings file
// is parsed. // is parsed.
NSString* EscapeForStringsFileValue(NSString* str) { std::string EscapeForStringsFileValue(std::string str) {
NSMutableString* worker = [NSMutableString stringWithString:str];
// Since this is a build tool, we don't really worry about making this // Since this is a build tool, we don't really worry about making this
// the most efficient code. // the most efficient code.
// Backslash first since we need to do it before we put in all the others // Backslash first since we need to do it before we put in all the others
[worker replaceOccurrencesOfString:@"\\" base::ReplaceChars(str, "\\", "\\\\", &str);
withString:@"\\\\"
options:NSLiteralSearch
range:NSMakeRange(0, [worker length])];
// Now the rest of them. // Now the rest of them.
[worker replaceOccurrencesOfString:@"\n" base::ReplaceChars(str, "\n", "\\n", &str);
withString:@"\\n" base::ReplaceChars(str, "\r", "\\r", &str);
options:NSLiteralSearch base::ReplaceChars(str, "\t", "\\t", &str);
range:NSMakeRange(0, [worker length])]; base::ReplaceChars(str, "\"", "\\\"", &str);
[worker replaceOccurrencesOfString:@"\r"
withString:@"\\r" return str;
options:NSLiteralSearch
range:NSMakeRange(0, [worker length])];
[worker replaceOccurrencesOfString:@"\t"
withString:@"\\t"
options:NSLiteralSearch
range:NSMakeRange(0, [worker length])];
[worker replaceOccurrencesOfString:@"\""
withString:@"\\\""
options:NSLiteralSearch
range:NSMakeRange(0, [worker length])];
return [[worker copy] autorelease];
} }
// The valid types for the -t arg // The valid types for the -t arg
const char kAppType_Main[] = "main"; // Main app const char kAppType_Main[] = "main"; // Main app
const char kAppType_Helper[] = "helper"; // Helper app const char kAppType_Helper[] = "helper"; // Helper app
} // namespace } // namespace
int main(int argc, char* const argv[]) { int main(int argc, char* const argv[]) {
@autoreleasepool { // FIXME: Remove the local block in a follow-up. Keeping it for now to keep
const char* version_string = NULL; // the diff cleaner.
const char* grit_output_dir = NULL; {
const char* branding_strings_name = NULL; const char* version_string = nullptr;
const char* output_dir = NULL; const char* grit_output_dir = nullptr;
const char* branding_strings_name = nullptr;
const char* output_dir = nullptr;
const char* app_type = kAppType_Main; const char* app_type = kAppType_Main;
// Process the args // Process the args
...@@ -150,21 +116,17 @@ int main(int argc, char* const argv[]) { ...@@ -150,21 +116,17 @@ int main(int argc, char* const argv[]) {
output_dir = optarg; output_dir = optarg;
break; break;
default: default:
fprintf(stderr, "ERROR: bad command line arg\n"); LOG(FATAL) << "bad command line arg";
exit(1);
break; break;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
#define CHECK_ARG(a, b) \ #define CHECK_ARG(a, b) \
do { \ do { \
if ((a)) { \ LOG_IF(FATAL, (a)) << b; \
fprintf(stderr, "ERROR: " b "\n"); \ } while (false)
exit(1); \
} \
} while (false)
// Check our args // Check our args
CHECK_ARG(!version_string, "Missing version string"); CHECK_ARG(!version_string, "Missing version string");
...@@ -181,19 +143,14 @@ int main(int argc, char* const argv[]) { ...@@ -181,19 +143,14 @@ int main(int argc, char* const argv[]) {
base::i18n::InitializeICU(); base::i18n::InitializeICU();
NSFileManager* fm = [NSFileManager defaultManager];
for (int loop = 0; loop < lang_list_count; ++loop) { for (int loop = 0; loop < lang_list_count; ++loop) {
const char* cur_lang = lang_list[loop]; std::string cur_lang = lang_list[loop];
// Open the branded string pak file // Open the branded string pak file
std::unique_ptr<ui::DataPack> branded_data_pack( std::unique_ptr<ui::DataPack> branded_data_pack(LoadResourceDataPack(
LoadResourceDataPack(grit_output_dir, branding_strings_name, cur_lang)); grit_output_dir, branding_strings_name, cur_lang));
if (branded_data_pack.get() == NULL) { CHECK(branded_data_pack)
fprintf(stderr, "ERROR: Failed to load branded pak for language: %s\n", << "failed to load branded pak for language: " << cur_lang;
cur_lang);
exit(1);
}
uint32_t name_id = IDS_PRODUCT_NAME; uint32_t name_id = IDS_PRODUCT_NAME;
const char* name_id_str = "IDS_PRODUCT_NAME"; const char* name_id_str = "IDS_PRODUCT_NAME";
...@@ -203,93 +160,65 @@ int main(int argc, char* const argv[]) { ...@@ -203,93 +160,65 @@ int main(int argc, char* const argv[]) {
} }
// Fetch the strings. // Fetch the strings.
NSString* name = std::string name = LoadStringFromDataPack(branded_data_pack.get(),
LoadStringFromDataPack(branded_data_pack.get(), cur_lang, cur_lang, name_id, name_id_str);
name_id, name_id_str); std::string copyright_format = LoadStringFromDataPack(
NSString* copyright_format = branded_data_pack.get(), cur_lang, IDS_ABOUT_VERSION_COPYRIGHT,
LoadStringFromDataPack(branded_data_pack.get(), cur_lang, "IDS_ABOUT_VERSION_COPYRIGHT");
IDS_ABOUT_VERSION_COPYRIGHT,
"IDS_ABOUT_VERSION_COPYRIGHT");
NSString* copyright = base::SysUTF16ToNSString( std::string copyright = base::UTF16ToUTF8(
base::i18n::MessageFormatter::FormatWithNumberedArgs( base::i18n::MessageFormatter::FormatWithNumberedArgs(
base::SysNSStringToUTF16(copyright_format), base::Time::Now())); base::UTF8ToUTF16(copyright_format), base::Time::Now()));
NSString* permission_reason = std::string permission_reason =
LoadStringFromDataPack(branded_data_pack.get(), cur_lang, LoadStringFromDataPack(branded_data_pack.get(), cur_lang,
IDS_RUNTIME_PERMISSION_OS_REASON_TEXT, IDS_RUNTIME_PERMISSION_OS_REASON_TEXT,
"IDS_RUNTIME_PERMISSION_OS_REASON_TEXT"); "IDS_RUNTIME_PERMISSION_OS_REASON_TEXT");
// For now, assume this is ok for all languages. If we need to, this could // For now, assume this is ok for all languages. If we need to, this could
// be moved into generated_resources.grd and fetched. // be moved into generated_resources.grd and fetched.
NSString* get_info = [NSString std::string get_info = base::StringPrintf(
stringWithFormat:@"%@ %s, %@", name, version_string, copyright]; "%s %s, %s", name.c_str(), version_string, copyright.c_str());
// Generate the InfoPlist.strings file contents. // Generate the InfoPlist.strings file contents.
NSDictionary<NSString*, NSString*>* infoplist_strings = @{ std::map<std::string, std::string> infoplist_strings = {
@"CFBundleGetInfoString" : get_info, {"CFBundleGetInfoString", get_info},
@"NSHumanReadableCopyright" : copyright, {"NSHumanReadableCopyright", copyright},
@"NSBluetoothAlwaysUsageDescription" : permission_reason, {"NSBluetoothAlwaysUsageDescription", permission_reason},
@"NSBluetoothPeripheralUsageDescription" : permission_reason, {"NSBluetoothPeripheralUsageDescription", permission_reason},
@"NSCameraUsageDescription" : permission_reason, {"NSCameraUsageDescription", permission_reason},
@"NSLocationUsageDescription" : permission_reason, {"NSLocationUsageDescription", permission_reason},
@"NSMicrophoneUsageDescription" : permission_reason, {"NSMicrophoneUsageDescription", permission_reason},
}; };
base::scoped_nsobject<NSMutableString> strings_file_contents_string( std::string strings_file_contents_string;
[[NSMutableString alloc] init]); for (const auto& kv : infoplist_strings) {
for (NSString* key in infoplist_strings) { strings_file_contents_string +=
[strings_file_contents_string base::StringPrintf("%s = \"%s\";\n", kv.first.c_str(),
appendFormat:@"%@ = \"%@\";\n", key, EscapeForStringsFileValue(kv.second).c_str());
EscapeForStringsFileValue(infoplist_strings[key])];
}
// We set up Xcode projects expecting strings files to be UTF8, so make
// sure we write the data in that form. When Xcode copies them it will
// put them final runtime encoding.
NSData* strings_file_contents_utf8 =
[strings_file_contents_string dataUsingEncoding:NSUTF8StringEncoding];
if ([strings_file_contents_utf8 length] == 0) {
fprintf(stderr, "ERROR: failed to get the utf8 encoding of the strings "
"file for language: %s\n", cur_lang);
exit(1);
} }
// For Cocoa to find the locale at runtime, it needs to use '_' instead of // For Cocoa to find the locale at runtime, it needs to use '_' instead of
// '-' (http://crbug.com/20441). Also, 'en-US' should be represented // '-' (http://crbug.com/20441). Also, 'en-US' should be represented
// simply as 'en' (http://crbug.com/19165, http://crbug.com/25578). // simply as 'en' (http://crbug.com/19165, http://crbug.com/25578).
NSString* cur_lang_ns = [NSString stringWithUTF8String:cur_lang]; if (cur_lang == "en-US")
if ([cur_lang_ns isEqualToString:@"en-US"]) { cur_lang = "en";
cur_lang_ns = @"en"; base::ReplaceChars(cur_lang, "-", "_", &cur_lang);
}
cur_lang_ns = [cur_lang_ns stringByReplacingOccurrencesOfString:@"-"
withString:@"_"];
// Make sure the lproj we write to exists // Make sure the lproj we write to exists
NSString *lproj_name = [NSString stringWithFormat:@"%@.lproj", cur_lang_ns]; std::string output_path =
NSString *output_path = base::StringPrintf("%s/%s.lproj", output_dir, cur_lang.c_str());
[[NSString stringWithUTF8String:output_dir] CHECK(base::CreateDirectory(base::FilePath(output_path)))
stringByAppendingPathComponent:lproj_name]; << "failed to create '" << output_path << "'";
NSError* error = nil;
if (![fm fileExistsAtPath:output_path] &&
![fm createDirectoryAtPath:output_path
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
fprintf(stderr, "ERROR: '%s' didn't exist or we failed to create it\n",
[output_path UTF8String]);
exit(1);
}
// Write out the file // Write out the file
output_path = // We set up Xcode projects expecting strings files to be UTF8, so make
[output_path stringByAppendingPathComponent:@"InfoPlist.strings"]; // sure we write the data in that form. When Xcode copies them it will
if (![strings_file_contents_utf8 writeToFile:output_path // put the final runtime encoding.
atomically:YES]) { output_path += "/InfoPlist.strings";
fprintf(stderr, "ERROR: Failed to write out '%s'\n", CHECK(base::WriteFile(base::FilePath(output_path),
[output_path UTF8String]); strings_file_contents_string))
exit(1); << "failed to write out '" << output_path << "'";
}
} }
return 0; return 0;
} }
......
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