OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/base/resource/resource_bundle_android.h" | 5 #include "ui/base/resource/resource_bundle_android.h" |
6 | 6 |
7 #include "base/android/apk_assets.h" | 7 #include "base/android/apk_assets.h" |
8 #include "base/android/jni_android.h" | 8 #include "base/android/jni_android.h" |
9 #include "base/android/jni_string.h" | 9 #include "base/android/jni_string.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/ptr_util.h" | |
11 #include "base/path_service.h" | 12 #include "base/path_service.h" |
12 #include "jni/ResourceBundle_jni.h" | 13 #include "jni/ResourceBundle_jni.h" |
13 #include "ui/base/l10n/l10n_util.h" | 14 #include "ui/base/l10n/l10n_util.h" |
14 #include "ui/base/resource/data_pack.h" | 15 #include "ui/base/resource/data_pack.h" |
15 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
16 #include "ui/base/ui_base_paths.h" | 17 #include "ui/base/ui_base_paths.h" |
17 | 18 |
18 namespace ui { | 19 namespace ui { |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 bool g_locale_paks_in_apk = false; | 23 bool g_locale_paks_in_apk = false; |
24 bool g_load_secondary_locale_paks = false; | |
23 // It is okay to cache and share these file descriptors since the | 25 // It is okay to cache and share these file descriptors since the |
24 // ResourceBundle singleton never closes the handles. | 26 // ResourceBundle singleton never closes the handles. |
25 int g_chrome_100_percent_fd = -1; | 27 int g_chrome_100_percent_fd = -1; |
26 int g_resources_pack_fd = -1; | 28 int g_resources_pack_fd = -1; |
27 int g_locale_pack_fd = -1; | 29 int g_locale_pack_fd = -1; |
30 int g_secondary_locale_pack_fd = -1; | |
28 base::MemoryMappedFile::Region g_chrome_100_percent_region; | 31 base::MemoryMappedFile::Region g_chrome_100_percent_region; |
29 base::MemoryMappedFile::Region g_resources_pack_region; | 32 base::MemoryMappedFile::Region g_resources_pack_region; |
30 base::MemoryMappedFile::Region g_locale_pack_region; | 33 base::MemoryMappedFile::Region g_locale_pack_region; |
34 base::MemoryMappedFile::Region g_secondary_locale_pack_region; | |
31 | 35 |
32 bool LoadFromApkOrFile(const char* apk_path, | 36 bool LoadFromApkOrFile(const char* apk_path, |
33 const base::FilePath* disk_path, | 37 const base::FilePath* disk_path, |
34 int* fd_out, | 38 int* fd_out, |
35 base::MemoryMappedFile::Region* region_out) { | 39 base::MemoryMappedFile::Region* out_region) { |
agrieve
2017/06/29 01:09:53
nit: this now doesn't match the other out param (f
F
2017/06/29 18:31:20
Done. I put "out" in front of "fd/region" because
| |
36 DCHECK_EQ(*fd_out, -1) << "Attempt to load " << apk_path << " twice."; | 40 DCHECK_EQ(*fd_out, -1) << "Attempt to load " << apk_path << " twice."; |
37 if (apk_path != nullptr) { | 41 if (apk_path != nullptr) { |
38 *fd_out = base::android::OpenApkAsset(apk_path, region_out); | 42 *fd_out = base::android::OpenApkAsset(apk_path, out_region); |
39 } | 43 } |
40 // For unit tests, the file exists on disk. | 44 // For unit tests, the file exists on disk. |
41 if (*fd_out < 0 && disk_path != nullptr) { | 45 if (*fd_out < 0 && disk_path != nullptr) { |
42 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; | 46 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
43 *fd_out = base::File(*disk_path, flags).TakePlatformFile(); | 47 *fd_out = base::File(*disk_path, flags).TakePlatformFile(); |
44 *region_out = base::MemoryMappedFile::Region::kWholeFile; | 48 *out_region = base::MemoryMappedFile::Region::kWholeFile; |
45 } | 49 } |
46 bool success = *fd_out >= 0; | 50 bool success = *fd_out >= 0; |
47 if (!success) { | 51 if (!success) { |
48 LOG(ERROR) << "Failed to open pak file: " << apk_path; | 52 LOG(ERROR) << "Failed to open pak file: " << apk_path; |
49 } | 53 } |
50 return success; | 54 return success; |
51 } | 55 } |
52 | 56 |
57 int LoadLocalePakFromApk(const std::string& app_locale, | |
agrieve
2017/06/29 01:09:53
nit: might be nice to match the signature of the a
F
2017/06/29 18:31:21
Resolved offline.
| |
58 base::MemoryMappedFile::Region* out_region) { | |
59 std::string locale_path_within_apk = | |
60 GetPathForAndroidLocalePakWithinApk(app_locale); | |
61 if (locale_path_within_apk.empty()) { | |
62 LOG(WARNING) << "locale_path_within_apk.empty() for locale " | |
agrieve
2017/06/29 01:09:53
nit: Probably worth using ERROR here
F
2017/06/29 18:31:20
Done.
| |
63 << app_locale; | |
64 return -1; | |
65 } | |
66 return base::android::OpenApkAsset(locale_path_within_apk, out_region); | |
67 } | |
68 | |
69 std::unique_ptr<DataPack> LoadDataPackFromLocalePak( | |
70 int locale_pack_fd, | |
71 const base::MemoryMappedFile::Region& region) { | |
72 std::unique_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P)); | |
73 if (!data_pack->LoadFromFileRegion(base::File(locale_pack_fd), region)) { | |
74 LOG(ERROR) << "failed to load locale.pak"; | |
agrieve
2017/06/29 01:09:53
nit: just << to the NOTREACHED().
F
2017/06/29 18:31:21
Resolved offline.
| |
75 NOTREACHED(); | |
76 return nullptr; | |
77 } | |
78 return data_pack; | |
79 } | |
80 | |
53 } // namespace | 81 } // namespace |
54 | 82 |
55 void ResourceBundle::LoadCommonResources() { | 83 void ResourceBundle::LoadCommonResources() { |
56 base::FilePath disk_path; | 84 base::FilePath disk_path; |
57 PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &disk_path); | 85 PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &disk_path); |
58 disk_path = disk_path.AppendASCII("chrome_100_percent.pak"); | 86 disk_path = disk_path.AppendASCII("chrome_100_percent.pak"); |
59 if (LoadFromApkOrFile("assets/chrome_100_percent.pak", | 87 if (LoadFromApkOrFile("assets/chrome_100_percent.pak", |
60 &disk_path, | 88 &disk_path, |
61 &g_chrome_100_percent_fd, | 89 &g_chrome_100_percent_fd, |
62 &g_chrome_100_percent_region)) { | 90 &g_chrome_100_percent_region)) { |
63 AddDataPackFromFileRegion(base::File(g_chrome_100_percent_fd), | 91 AddDataPackFromFileRegion(base::File(g_chrome_100_percent_fd), |
64 g_chrome_100_percent_region, SCALE_FACTOR_100P); | 92 g_chrome_100_percent_region, SCALE_FACTOR_100P); |
65 } | 93 } |
66 } | 94 } |
67 | 95 |
68 bool ResourceBundle::LocaleDataPakExists(const std::string& locale) { | 96 bool ResourceBundle::LocaleDataPakExists(const std::string& locale) { |
69 if (g_locale_paks_in_apk) { | 97 if (g_locale_paks_in_apk) { |
70 return !GetPathForAndroidLocalePakWithinApk(locale).empty(); | 98 return !GetPathForAndroidLocalePakWithinApk(locale).empty(); |
71 } | 99 } |
72 return !GetLocaleFilePath(locale, true).empty(); | 100 return !GetLocaleFilePath(locale, true).empty(); |
73 } | 101 } |
74 | 102 |
75 std::string ResourceBundle::LoadLocaleResources( | 103 std::string ResourceBundle::LoadLocaleResources( |
76 const std::string& pref_locale) { | 104 const std::string& pref_locale) { |
77 DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded"; | 105 DCHECK(!locale_resources_data_.get() && |
106 !secondary_locale_resources_data_.get()) | |
107 << "locale.pak already loaded"; | |
78 if (g_locale_pack_fd != -1) { | 108 if (g_locale_pack_fd != -1) { |
79 LOG(WARNING) | 109 LOG(WARNING) |
80 << "Unexpected (outside of tests): Loading a second locale pak file."; | 110 << "Unexpected (outside of tests): Loading a second locale pak file."; |
81 } | 111 } |
82 std::string app_locale = l10n_util::GetApplicationLocale(pref_locale); | 112 std::string app_locale = l10n_util::GetApplicationLocale(pref_locale); |
113 | |
114 // Load primary locale .pak file. | |
83 if (g_locale_paks_in_apk) { | 115 if (g_locale_paks_in_apk) { |
84 std::string locale_path_within_apk = | 116 g_locale_pack_fd = LoadLocalePakFromApk(app_locale, &g_locale_pack_region); |
85 GetPathForAndroidLocalePakWithinApk(app_locale); | |
86 if (locale_path_within_apk.empty()) { | |
87 LOG(WARNING) << "locale_path_within_apk.empty() for locale " | |
88 << app_locale; | |
89 return std::string(); | |
90 } | |
91 g_locale_pack_fd = base::android::OpenApkAsset(locale_path_within_apk, | |
92 &g_locale_pack_region); | |
93 } else { | 117 } else { |
94 base::FilePath locale_file_path = GetOverriddenPakPath(); | 118 base::FilePath locale_file_path = GetOverriddenPakPath(); |
95 if (locale_file_path.empty()) | 119 if (locale_file_path.empty()) |
96 locale_file_path = GetLocaleFilePath(app_locale, true); | 120 locale_file_path = GetLocaleFilePath(app_locale, true); |
97 | 121 |
98 if (locale_file_path.empty()) { | 122 if (locale_file_path.empty()) { |
99 // It's possible that there is no locale.pak. | 123 // It's possible that there is no locale.pak. |
100 LOG(WARNING) << "locale_file_path.empty() for locale " << app_locale; | 124 LOG(WARNING) << "locale_file_path.empty() for locale " << app_locale; |
101 return std::string(); | 125 return std::string(); |
102 } | 126 } |
103 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; | 127 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
104 g_locale_pack_fd = base::File(locale_file_path, flags).TakePlatformFile(); | 128 g_locale_pack_fd = base::File(locale_file_path, flags).TakePlatformFile(); |
105 g_locale_pack_region = base::MemoryMappedFile::Region::kWholeFile; | 129 g_locale_pack_region = base::MemoryMappedFile::Region::kWholeFile; |
106 } | 130 } |
107 | 131 |
108 std::unique_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P)); | 132 locale_resources_data_ = LoadDataPackFromLocalePak( |
109 if (!data_pack->LoadFromFileRegion(base::File(g_locale_pack_fd), | 133 g_locale_pack_fd, g_locale_pack_region); |
110 g_locale_pack_region)) { | 134 |
111 LOG(ERROR) << "failed to load locale.pak"; | 135 if (!locale_resources_data_.get()) |
112 NOTREACHED(); | |
113 return std::string(); | 136 return std::string(); |
137 | |
138 // Load secondary locale .pak file if it exists. For debug build monochrome, | |
139 // a secondary locale pak will always be loaded; however, it should be | |
140 // unnecessary for loading locale resources. | |
agrieve
2017/06/29 01:09:53
nit: say why it's unnecessary.
F
2017/06/29 18:31:21
Done.
| |
141 if (g_load_secondary_locale_paks) { | |
142 g_secondary_locale_pack_fd = LoadLocalePakFromApk( | |
143 app_locale, &g_secondary_locale_pack_region); | |
144 | |
145 secondary_locale_resources_data_ = LoadDataPackFromLocalePak( | |
146 g_secondary_locale_pack_fd, g_secondary_locale_pack_region); | |
147 | |
148 if (!secondary_locale_resources_data_.get()) | |
agrieve
2017/06/29 01:09:53
nit: probably fine to omit this early return since
F
2017/06/29 18:31:21
Resolved offline.
| |
149 return std::string(); | |
114 } | 150 } |
115 | 151 |
116 locale_resources_data_ = std::move(data_pack); | |
117 return app_locale; | 152 return app_locale; |
118 } | 153 } |
119 | 154 |
120 gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { | 155 gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { |
121 return GetImageNamed(resource_id); | 156 return GetImageNamed(resource_id); |
122 } | 157 } |
123 | 158 |
124 void SetLocalePaksStoredInApk(bool value) { | 159 void SetLocalePaksStoredInApk(bool value) { |
125 g_locale_paks_in_apk = value; | 160 g_locale_paks_in_apk = value; |
126 } | 161 } |
127 | 162 |
163 void SetLoadSecondaryLocalePaks(bool value) { | |
164 g_load_secondary_locale_paks = value; | |
165 } | |
166 | |
128 void LoadMainAndroidPackFile(const char* path_within_apk, | 167 void LoadMainAndroidPackFile(const char* path_within_apk, |
129 const base::FilePath& disk_file_path) { | 168 const base::FilePath& disk_file_path) { |
130 if (LoadFromApkOrFile(path_within_apk, | 169 if (LoadFromApkOrFile(path_within_apk, |
131 &disk_file_path, | 170 &disk_file_path, |
132 &g_resources_pack_fd, | 171 &g_resources_pack_fd, |
133 &g_resources_pack_region)) { | 172 &g_resources_pack_region)) { |
134 ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion( | 173 ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion( |
135 base::File(g_resources_pack_fd), g_resources_pack_region, | 174 base::File(g_resources_pack_fd), g_resources_pack_region, |
136 SCALE_FACTOR_NONE); | 175 SCALE_FACTOR_NONE); |
137 } | 176 } |
(...skipping 10 matching lines...) Expand all Loading... | |
148 *out_region = g_chrome_100_percent_region; | 187 *out_region = g_chrome_100_percent_region; |
149 return g_chrome_100_percent_fd; | 188 return g_chrome_100_percent_fd; |
150 } | 189 } |
151 | 190 |
152 int GetLocalePackFd(base::MemoryMappedFile::Region* out_region) { | 191 int GetLocalePackFd(base::MemoryMappedFile::Region* out_region) { |
153 DCHECK_GE(g_locale_pack_fd, 0); | 192 DCHECK_GE(g_locale_pack_fd, 0); |
154 *out_region = g_locale_pack_region; | 193 *out_region = g_locale_pack_region; |
155 return g_locale_pack_fd; | 194 return g_locale_pack_fd; |
156 } | 195 } |
157 | 196 |
197 int GetSecondaryLocalePackFd(base::MemoryMappedFile::Region* out_region) { | |
198 *out_region = g_secondary_locale_pack_region; | |
199 return g_secondary_locale_pack_fd; | |
200 } | |
201 | |
158 std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale) { | 202 std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale) { |
159 JNIEnv* env = base::android::AttachCurrentThread(); | 203 JNIEnv* env = base::android::AttachCurrentThread(); |
160 base::android::ScopedJavaLocalRef<jstring> ret = | 204 base::android::ScopedJavaLocalRef<jstring> ret = |
161 Java_ResourceBundle_getLocalePakResourcePath( | 205 Java_ResourceBundle_getLocalePakResourcePath( |
162 env, base::android::ConvertUTF8ToJavaString(env, locale)); | 206 env, base::android::ConvertUTF8ToJavaString(env, locale)); |
163 if (ret.obj() == nullptr) { | 207 if (ret.obj() == nullptr) { |
164 return std::string(); | 208 return std::string(); |
165 } | 209 } |
166 return base::android::ConvertJavaStringToUTF8(env, ret.obj()); | 210 return base::android::ConvertJavaStringToUTF8(env, ret.obj()); |
167 } | 211 } |
168 | 212 |
169 float GetPrimaryDisplayScale() { | 213 float GetPrimaryDisplayScale() { |
170 return Java_ResourceBundle_getPrimaryDisplayScale( | 214 return Java_ResourceBundle_getPrimaryDisplayScale( |
171 base::android::AttachCurrentThread()); | 215 base::android::AttachCurrentThread()); |
172 } | 216 } |
173 | 217 |
174 } // namespace ui | 218 } // namespace ui |
OLD | NEW |