Durable Storage: Refactor browser test and test the basic "deny" flow.
[chromium-blink-merge.git] / ui / base / resource / resource_bundle_android.cc
blobae731d680cb4849d6fd7a78716abd52226a88196
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
3 // found in the LICENSE file.
5 #include "ui/base/resource/resource_bundle_android.h"
7 #include "base/android/apk_assets.h"
8 #include "base/android/jni_android.h"
9 #include "base/android/jni_string.h"
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/path_service.h"
13 #include "jni/ResourceBundle_jni.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/base/resource/data_pack.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/base/ui_base_paths.h"
19 namespace ui {
21 namespace {
23 bool g_locale_paks_in_apk = false;
24 // It is okay to cache and share these file descriptors since the
25 // ResourceBundle singleton never closes the handles.
26 int g_chrome_100_percent_fd = -1;
27 int g_resources_pack_fd = -1;
28 int g_locale_pack_fd = -1;
29 base::MemoryMappedFile::Region g_chrome_100_percent_region;
30 base::MemoryMappedFile::Region g_resources_pack_region;
31 base::MemoryMappedFile::Region g_locale_pack_region;
33 bool LoadFromApkOrFile(const char* apk_path,
34 const base::FilePath* disk_path,
35 int* fd_out,
36 base::MemoryMappedFile::Region* region_out) {
37 DCHECK_EQ(*fd_out, -1) << "Attempt to load " << apk_path << " twice.";
38 if (apk_path != nullptr) {
39 *fd_out = base::android::OpenApkAsset(apk_path, region_out);
41 // For unit tests, the file exists on disk.
42 if (*fd_out < 0 && disk_path != nullptr) {
43 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
44 *fd_out = base::File(*disk_path, flags).TakePlatformFile();
45 *region_out = base::MemoryMappedFile::Region::kWholeFile;
47 bool success = *fd_out >= 0;
48 if (!success) {
49 LOG(ERROR) << "Failed to open pak file: " << apk_path;
51 return success;
54 } // namespace
56 void ResourceBundle::LoadCommonResources() {
57 base::FilePath disk_path;
58 PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &disk_path);
59 disk_path = disk_path.AppendASCII("chrome_100_percent.pak");
60 if (LoadFromApkOrFile("assets/chrome_100_percent.pak",
61 &disk_path,
62 &g_chrome_100_percent_fd,
63 &g_chrome_100_percent_region)) {
64 AddDataPackFromFileRegion(base::File(g_chrome_100_percent_fd),
65 g_chrome_100_percent_region, SCALE_FACTOR_100P);
69 bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
70 if (g_locale_paks_in_apk) {
71 return !GetPathForAndroidLocalePakWithinApk(locale).empty();
73 return !GetLocaleFilePath(locale, true).empty();
76 std::string ResourceBundle::LoadLocaleResources(
77 const std::string& pref_locale) {
78 DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded";
79 if (g_locale_pack_fd != -1) {
80 LOG(WARNING)
81 << "Unexpected (outside of tests): Loading a second locale pak file.";
83 std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
84 if (g_locale_paks_in_apk) {
85 std::string locale_path_within_apk =
86 GetPathForAndroidLocalePakWithinApk(app_locale);
87 if (locale_path_within_apk.empty()) {
88 LOG(WARNING) << "locale_path_within_apk.empty() for locale "
89 << app_locale;
90 return std::string();
92 g_locale_pack_fd = base::android::OpenApkAsset(locale_path_within_apk,
93 &g_locale_pack_region);
94 } else {
95 base::FilePath locale_file_path = GetOverriddenPakPath();
96 if (locale_file_path.empty())
97 locale_file_path = GetLocaleFilePath(app_locale, true);
99 if (locale_file_path.empty()) {
100 // It's possible that there is no locale.pak.
101 LOG(WARNING) << "locale_file_path.empty() for locale " << app_locale;
102 return std::string();
104 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
105 g_locale_pack_fd = base::File(locale_file_path, flags).TakePlatformFile();
106 g_locale_pack_region = base::MemoryMappedFile::Region::kWholeFile;
109 scoped_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P));
110 if (!data_pack->LoadFromFileRegion(base::File(g_locale_pack_fd),
111 g_locale_pack_region)) {
112 UMA_HISTOGRAM_ENUMERATION("ResourceBundle.LoadLocaleResourcesError",
113 logging::GetLastSystemErrorCode(), 16000);
114 LOG(ERROR) << "failed to load locale.pak";
115 NOTREACHED();
116 return std::string();
119 locale_resources_data_.reset(data_pack.release());
120 return app_locale;
123 gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
124 // Flipped image is not used on Android.
125 DCHECK_EQ(rtl, RTL_DISABLED);
126 return GetImageNamed(resource_id);
129 void SetLocalePaksStoredInApk(bool value) {
130 g_locale_paks_in_apk = value;
133 void LoadMainAndroidPackFile(const char* path_within_apk,
134 const base::FilePath& disk_file_path) {
135 if (LoadFromApkOrFile(path_within_apk,
136 &disk_file_path,
137 &g_resources_pack_fd,
138 &g_resources_pack_region)) {
139 ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
140 base::File(g_resources_pack_fd), g_resources_pack_region,
141 SCALE_FACTOR_NONE);
145 int GetMainAndroidPackFd(base::MemoryMappedFile::Region* out_region) {
146 DCHECK_GE(g_resources_pack_fd, 0);
147 *out_region = g_resources_pack_region;
148 return g_resources_pack_fd;
151 int GetCommonResourcesPackFd(base::MemoryMappedFile::Region* out_region) {
152 DCHECK_GE(g_chrome_100_percent_fd, 0);
153 *out_region = g_chrome_100_percent_region;
154 return g_chrome_100_percent_fd;
157 int GetLocalePackFd(base::MemoryMappedFile::Region* out_region) {
158 DCHECK_GE(g_locale_pack_fd, 0);
159 *out_region = g_locale_pack_region;
160 return g_locale_pack_fd;
163 std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale) {
164 JNIEnv* env = base::android::AttachCurrentThread();
165 base::android::ScopedJavaLocalRef<jstring> ret =
166 Java_ResourceBundle_getLocalePakResourcePath(
167 env, base::android::ConvertUTF8ToJavaString(env, locale).obj());
168 if (ret.obj() == nullptr) {
169 return std::string();
171 return base::android::ConvertJavaStringToUTF8(env, ret.obj());
174 bool RegisterResourceBundleAndroid(JNIEnv* env) {
175 return RegisterNativesImpl(env);
178 } // namespace ui