summaryrefslogtreecommitdiffstats
path: root/app/resource_bundle_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'app/resource_bundle_linux.cc')
-rw-r--r--app/resource_bundle_linux.cc209
1 files changed, 209 insertions, 0 deletions
diff --git a/app/resource_bundle_linux.cc b/app/resource_bundle_linux.cc
new file mode 100644
index 0000000..9c866b2
--- /dev/null
+++ b/app/resource_bundle_linux.cc
@@ -0,0 +1,209 @@
+// Copyright (c) 2006-2008 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 "app/resource_bundle.h"
+
+#include <gtk/gtk.h>
+
+#include "base/base_paths.h"
+#include "base/data_pack.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/gfx/gtk_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/gfx/chrome_font.h"
+#include "chrome/common/gtk_util.h"
+#include "chrome/common/l10n_util.h"
+#include "SkBitmap.h"
+
+namespace {
+
+// Convert the raw image data into a GdkPixbuf. The GdkPixbuf that is returned
+// has a ref count of 1 so the caller must call g_object_unref to free the
+// memory.
+GdkPixbuf* LoadPixbuf(std::vector<unsigned char>& data) {
+ ScopedGObject<GdkPixbufLoader>::Type loader(gdk_pixbuf_loader_new());
+ bool ok = gdk_pixbuf_loader_write(loader.get(),
+ static_cast<guint8*>(data.data()), data.size(), NULL);
+ if (!ok)
+ return NULL;
+ // Calling gdk_pixbuf_loader_close forces the data to be parsed by the
+ // loader. We must do this before calling gdk_pixbuf_loader_get_pixbuf.
+ ok = gdk_pixbuf_loader_close(loader.get(), NULL);
+ if (!ok)
+ return NULL;
+ GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader.get());
+ if (!pixbuf)
+ return NULL;
+
+ // The pixbuf is owned by the loader, so add a ref so when we delete the
+ // loader (when the ScopedGObject goes out of scope), the pixbuf still
+ // exists.
+ g_object_ref(pixbuf);
+
+ return pixbuf;
+}
+
+} // namespace
+
+ResourceBundle::~ResourceBundle() {
+ FreeImages();
+ // Free GdkPixbufs.
+ for (GdkPixbufMap::iterator i = gdk_pixbufs_.begin();
+ i != gdk_pixbufs_.end(); i++) {
+ g_object_unref(i->second);
+ }
+ gdk_pixbufs_.clear();
+
+ delete locale_resources_data_;
+ locale_resources_data_ = NULL;
+ delete theme_data_;
+ theme_data_ = NULL;
+ delete resources_data_;
+ resources_data_ = NULL;
+}
+
+void ResourceBundle::LoadResources(const std::wstring& pref_locale) {
+ FilePath resources_data_path;
+ PathService::Get(base::DIR_EXE, &resources_data_path);
+ resources_data_path = resources_data_path.Append(
+ FILE_PATH_LITERAL("chrome.pak"));
+ DCHECK(resources_data_ == NULL) << "resource data already loaded!";
+ resources_data_ = new base::DataPack;
+ bool success = resources_data_->Load(resources_data_path);
+ DCHECK(success) << "failed to load chrome.pak";
+
+ DCHECK(locale_resources_data_ == NULL) << "locale data already loaded!";
+ const FilePath& locale_path = GetLocaleFilePath(pref_locale);
+ if (locale_path.value().empty()) {
+ // It's possible that there are no locale dlls found, in which case we just
+ // return.
+ NOTREACHED();
+ return;
+ }
+
+ locale_resources_data_ = new base::DataPack;
+ success = locale_resources_data_->Load(locale_path);
+ DCHECK(success) << "failed to load locale pak file";
+}
+
+FilePath ResourceBundle::GetLocaleFilePath(const std::wstring& pref_locale) {
+ FilePath locale_path;
+ PathService::Get(chrome::DIR_LOCALES, &locale_path);
+
+ const std::wstring app_locale = l10n_util::GetApplicationLocale(pref_locale);
+ if (app_locale.empty())
+ return FilePath();
+
+ return locale_path.Append(WideToASCII(app_locale + L".pak"));
+}
+
+void ResourceBundle::LoadThemeResources() {
+ FilePath theme_data_path;
+ PathService::Get(chrome::DIR_THEMES, &theme_data_path);
+ theme_data_path = theme_data_path.Append(FILE_PATH_LITERAL("default.pak"));
+ theme_data_ = new base::DataPack;
+ bool success = theme_data_->Load(theme_data_path);
+ DCHECK(success) << "failed to load theme data";
+}
+
+/* static */
+bool ResourceBundle::LoadResourceBytes(DataHandle module, int resource_id,
+ std::vector<unsigned char>* bytes) {
+ DCHECK(module);
+ StringPiece data;
+ if (!module->Get(resource_id, &data))
+ return false;
+
+ bytes->resize(data.length());
+ memcpy(&(bytes->front()), data.data(), data.length());
+
+ return true;
+}
+
+StringPiece ResourceBundle::GetRawDataResource(int resource_id) {
+ DCHECK(resources_data_);
+ StringPiece data;
+ if (!resources_data_->Get(resource_id, &data))
+ return StringPiece();
+ return data;
+}
+
+string16 ResourceBundle::GetLocalizedString(int message_id) {
+ // If for some reason we were unable to load a resource dll, return an empty
+ // string (better than crashing).
+ if (!locale_resources_data_) {
+ LOG(WARNING) << "locale resources are not loaded";
+ return string16();
+ }
+
+ StringPiece data;
+ if (!locale_resources_data_->Get(message_id, &data)) {
+ // Fall back on the main data pack (shouldn't be any strings here except in
+ // unittests).
+ data = GetRawDataResource(message_id);
+ if (data.empty()) {
+ NOTREACHED() << "unable to find resource: " << message_id;
+ return string16();
+ }
+ }
+
+ // Data pack encodes strings as UTF16.
+ string16 msg(reinterpret_cast<const char16*>(data.data()),
+ data.length() / 2);
+ return msg;
+}
+
+GdkPixbuf* ResourceBundle::GetPixbufNamed(int resource_id) {
+ // Check to see if we already have the pixbuf in the cache.
+ {
+ AutoLock lock_scope(lock_);
+ GdkPixbufMap::const_iterator found = gdk_pixbufs_.find(resource_id);
+ if (found != gdk_pixbufs_.end())
+ return found->second;
+ }
+
+
+ std::vector<unsigned char> data;
+ LoadImageResourceBytes(resource_id, &data);
+ GdkPixbuf* pixbuf = LoadPixbuf(data);
+
+ // We loaded successfully. Cache the pixbuf.
+ if (pixbuf) {
+ AutoLock lock_scope(lock_);
+
+ // Another thread raced us, and has already cached the pixbuf.
+ if (gdk_pixbufs_.count(resource_id)) {
+ g_object_unref(pixbuf);
+ return gdk_pixbufs_[resource_id];
+ }
+
+ gdk_pixbufs_[resource_id] = pixbuf;
+ return pixbuf;
+ }
+
+ // We failed to retrieve the bitmap, show a debugging red square.
+ {
+ LOG(WARNING) << "Unable to load GdkPixbuf with id " << resource_id;
+ NOTREACHED(); // Want to assert in debug mode.
+
+ AutoLock lock_scope(lock_); // Guard empty_bitmap initialization.
+
+ static GdkPixbuf* empty_bitmap = NULL;
+ if (!empty_bitmap) {
+ // The placeholder bitmap is bright red so people notice the problem.
+ // This bitmap will be leaked, but this code should never be hit.
+ scoped_ptr<SkBitmap> skia_bitmap(new SkBitmap());
+ skia_bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32);
+ skia_bitmap->allocPixels();
+ skia_bitmap->eraseARGB(255, 255, 0, 0);
+ empty_bitmap = gfx::GdkPixbufFromSkBitmap(skia_bitmap.get());
+ }
+ return empty_bitmap;
+ }
+}