diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/DEPS | 8 | ||||
-rw-r--r-- | app/app.vcproj | 139 | ||||
-rw-r--r-- | app/app.vsprops | 8 | ||||
-rw-r--r-- | app/resource_bundle.cc | 205 | ||||
-rw-r--r-- | app/resource_bundle.h | 203 | ||||
-rw-r--r-- | app/resource_bundle_linux.cc | 209 | ||||
-rw-r--r-- | app/resource_bundle_mac.mm | 120 | ||||
-rw-r--r-- | app/resource_bundle_win.cc | 157 |
8 files changed, 1049 insertions, 0 deletions
diff --git a/app/DEPS b/app/DEPS new file mode 100644 index 0000000..9ff54fa --- /dev/null +++ b/app/DEPS @@ -0,0 +1,8 @@ +include_rules = [ + "+net", + # TODO(beng): Sever this link once we have extracted all deps from + # chrome/common. + "+chrome/common", + # TODO(beng): Sever this link after glen fixes it. + "+chrome/browser/extensions/extension.h", +] diff --git a/app/app.vcproj b/app/app.vcproj new file mode 100644 index 0000000..22c1e1f --- /dev/null +++ b/app/app.vcproj @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="app"
+ ProjectGUID="{4631946D-7D5F-44BD-A5A8-504C0A7033BE}"
+ RootNamespace="app"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\app.vsprops;$(SolutionDir)..\build\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\app.vsprops;$(SolutionDir)..\build\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\resource_bundle.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\resource_bundle.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource_bundle_win.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/app/app.vsprops b/app/app.vsprops new file mode 100644 index 0000000..fb267c1 --- /dev/null +++ b/app/app.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="app"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\tools\grit\build\using_generated_resources.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\npapi\using_npapi.vsprops;$(SolutionDir)..\chrome\third_party\wtl\using_wtl.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/app/resource_bundle.cc b/app/resource_bundle.cc new file mode 100644 index 0000000..5b3c034 --- /dev/null +++ b/app/resource_bundle.cc @@ -0,0 +1,205 @@ +// Copyright (c) 2006-2009 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 "base/gfx/png_decoder.h" +#include "base/logging.h" +#include "base/string_piece.h" +#include "net/base/file_stream.h" +#include "net/base/net_errors.h" +#include "chrome/common/gfx/chrome_font.h" +#include "SkBitmap.h" + +ResourceBundle* ResourceBundle::g_shared_instance_ = NULL; + +/* static */ +void ResourceBundle::InitSharedInstance(const std::wstring& pref_locale) { + DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; + g_shared_instance_ = new ResourceBundle(); + + g_shared_instance_->LoadResources(pref_locale); +} + +/* static */ +void ResourceBundle::CleanupSharedInstance() { + if (g_shared_instance_) { + delete g_shared_instance_; + g_shared_instance_ = NULL; + } +} + +/* static */ +ResourceBundle& ResourceBundle::GetSharedInstance() { + // Must call InitSharedInstance before this function. + CHECK(g_shared_instance_ != NULL); + return *g_shared_instance_; +} + +ResourceBundle::ResourceBundle() + : resources_data_(NULL), + locale_resources_data_(NULL), + theme_data_(NULL) { +} + +void ResourceBundle::FreeImages() { + for (SkImageMap::iterator i = skia_images_.begin(); + i != skia_images_.end(); i++) { + delete i->second; + } + skia_images_.clear(); +} + +void ResourceBundle::SetThemeExtension(const Extension& e) { + theme_extension_.reset(new Extension(e)); +} + +/* static */ +SkBitmap* ResourceBundle::LoadBitmap(DataHandle data_handle, int resource_id) { + std::vector<unsigned char> raw_data, png_data; + bool success = false; + // First check to see if we have a registered theme extension and whether + // it can handle this resource. + // TODO(erikkay): It would be nice to use something less brittle than + // resource_id here. + if (g_shared_instance_->theme_extension_.get()) { + FilePath path = + g_shared_instance_->theme_extension_->GetThemeResourcePath(resource_id); + if (!path.empty()) { + net::FileStream file; + int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; + if (file.Open(path, flags) == net::OK) { + int64 avail = file.Available(); + if (avail > 0 && avail < INT_MAX) { + size_t size = static_cast<size_t>(avail); + raw_data.resize(size); + char* data = reinterpret_cast<char*>(&(raw_data.front())); + if (file.ReadUntilComplete(data, size) == avail) { + success= true; + } else { + raw_data.resize(0); + } + } + } + } + } + if (!success) + success = LoadResourceBytes(data_handle, resource_id, &raw_data); + if (!success) + return NULL; + + // Decode the PNG. + int image_width; + int image_height; + if (!PNGDecoder::Decode(&raw_data.front(), raw_data.size(), + PNGDecoder::FORMAT_BGRA, + &png_data, &image_width, &image_height)) { + NOTREACHED() << "Unable to decode image resource " << resource_id; + return NULL; + } + + return PNGDecoder::CreateSkBitmapFromBGRAFormat(png_data, + image_width, + image_height); +} + +std::string ResourceBundle::GetDataResource(int resource_id) { + return GetRawDataResource(resource_id).as_string(); +} + +bool ResourceBundle::LoadImageResourceBytes(int resource_id, + std::vector<unsigned char>* bytes) { + return LoadResourceBytes(theme_data_, resource_id, bytes); +} + +bool ResourceBundle::LoadDataResourceBytes(int resource_id, + std::vector<unsigned char>* bytes) { + return LoadResourceBytes(resources_data_, resource_id, bytes); +} + +SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) { + // Check to see if we already have the Skia image in the cache. + { + AutoLock lock_scope(lock_); + SkImageMap::const_iterator found = skia_images_.find(resource_id); + if (found != skia_images_.end()) + return found->second; + } + + scoped_ptr<SkBitmap> bitmap; + + if (theme_data_) + bitmap.reset(LoadBitmap(theme_data_, resource_id)); + + // If we did not find the bitmap in the theme DLL, try the current one. + if (!bitmap.get()) + bitmap.reset(LoadBitmap(resources_data_, resource_id)); + + // We loaded successfully. Cache the Skia version of the bitmap. + if (bitmap.get()) { + AutoLock lock_scope(lock_); + + // Another thread raced us, and has already cached the skia image. + if (skia_images_.count(resource_id)) + return skia_images_[resource_id]; + + skia_images_[resource_id] = bitmap.get(); + return bitmap.release(); + } + + // We failed to retrieve the bitmap, show a debugging red square. + { + LOG(WARNING) << "Unable to load bitmap with id " << resource_id; + NOTREACHED(); // Want to assert in debug mode. + + AutoLock lock_scope(lock_); // Guard empty_bitmap initialization. + + static SkBitmap* 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. + empty_bitmap = new SkBitmap(); + empty_bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32); + empty_bitmap->allocPixels(); + empty_bitmap->eraseARGB(255, 255, 0, 0); + } + return empty_bitmap; + } +} + +void ResourceBundle::LoadFontsIfNecessary() { + AutoLock lock_scope(lock_); + if (!base_font_.get()) { + base_font_.reset(new ChromeFont()); + + small_font_.reset(new ChromeFont()); + *small_font_ = base_font_->DeriveFont(-2); + + medium_font_.reset(new ChromeFont()); + *medium_font_ = base_font_->DeriveFont(3); + + medium_bold_font_.reset(new ChromeFont()); + *medium_bold_font_ = + base_font_->DeriveFont(3, base_font_->style() | ChromeFont::BOLD); + + large_font_.reset(new ChromeFont()); + *large_font_ = base_font_->DeriveFont(8); + } +} + +ChromeFont ResourceBundle::GetFont(FontStyle style) { + LoadFontsIfNecessary(); + switch(style) { + case SmallFont: + return *small_font_; + case MediumFont: + return *medium_font_; + case MediumBoldFont: + return *medium_bold_font_; + case LargeFont: + return *large_font_; + default: + return *base_font_; + } +} diff --git a/app/resource_bundle.h b/app/resource_bundle.h new file mode 100644 index 0000000..e3c572c --- /dev/null +++ b/app/resource_bundle.h @@ -0,0 +1,203 @@ +// Copyright (c) 2006-2009 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. + +#ifndef CHROME_COMMON_RESOURCE_BUNDLE_H__ +#define CHROME_COMMON_RESOURCE_BUNDLE_H__ + +#include "build/build_config.h" + +#if defined(OS_WIN) +#include <windows.h> +#endif + +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/lock.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/extensions/extension.h" + +#if defined(OS_LINUX) || defined(OS_MACOSX) +namespace base { + class DataPack; +}; +#endif +#if defined(OS_LINUX) +typedef struct _GdkPixbuf GdkPixbuf; +#endif +class ChromeFont; +class Extension; +class SkBitmap; +class StringPiece; + +// ResourceBundle is a central facility to load images and other resources, +// such as theme graphics. +// Every resource is loaded only once. +class ResourceBundle { + public: + // An enumeration of the various font styles used throughout Chrome. + // The following holds true for the font sizes: + // Small <= Base <= Medium <= MediumBold <= Large. + enum FontStyle { + SmallFont, + BaseFont, + MediumFont, + // NOTE: depending upon the locale, this may *not* result in a bold font. + MediumBoldFont, + LargeFont, + }; + + // Initialize the ResourceBundle for this process. + // NOTE: Mac ignores this and always loads up resources for the language + // defined by the Cocoa UI (ie-NSBundle does the langange work). + static void InitSharedInstance(const std::wstring& pref_locale); + + // Delete the ResourceBundle for this process if it exists. + static void CleanupSharedInstance(); + + // Return the global resource loader instance. + static ResourceBundle& GetSharedInstance(); + + // Load the data file that contains theme resources if present. + void LoadThemeResources(); + + // Gets the bitmap with the specified resource_id, first by looking into the + // theme data, than in the current module data if applicable. + // Returns a pointer to a shared instance of the SkBitmap. This shared bitmap + // is owned by the resource bundle and should not be freed. + // + // The bitmap is assumed to exist. This function will log in release, and + // assert in debug mode if it does not. On failure, this will return a + // pointer to a shared empty placeholder bitmap so it will be visible what + // is missing. + SkBitmap* GetBitmapNamed(int resource_id); + + // Loads the raw bytes of an image resource into |bytes|, + // without doing any processing or interpretation of + // the resource. Returns whether we successfully read the resource. + bool LoadImageResourceBytes(int resource_id, + std::vector<unsigned char>* bytes); + + // Loads the raw bytes of a data resource into |bytes|, + // without doing any processing or interpretation of + // the resource. Returns whether we successfully read the resource. + bool LoadDataResourceBytes(int resource_id, + std::vector<unsigned char>* bytes); + + // Return the contents of a file in a string given the resource id. + // This will copy the data from the resource and return it as a string. + // TODO(port): deprecate this and replace with GetRawDataResource to avoid + // needless copying. + std::string GetDataResource(int resource_id); + + // Like GetDataResource(), but avoids copying the resource. Instead, it + // returns a StringPiece which points into the actual resource in the image. + StringPiece GetRawDataResource(int resource_id); + + // Get a localized string given a message id. Returns an empty + // string if the message_id is not found. + string16 GetLocalizedString(int message_id); + + // Returns the font for the specified style. + ChromeFont GetFont(FontStyle style); + +#if defined(OS_WIN) + // Loads and returns an icon from the theme dll. + HICON LoadThemeIcon(int icon_id); + + // Loads and returns a cursor from the app module. + HCURSOR LoadCursor(int cursor_id); +#elif defined(OS_LINUX) + // Gets the GdkPixbuf with the specified resource_id, first by looking into + // the theme data, than in the current module data if applicable. Returns a + // pointer to a shared instance of the GdkPixbuf. This shared GdkPixbuf is + // owned by the resource bundle and should not be freed. + // + // The bitmap is assumed to exist. This function will log in release, and + // assert in debug mode if it does not. On failure, this will return a + // pointer to a shared empty placeholder bitmap so it will be visible what + // is missing. + GdkPixbuf* GetPixbufNamed(int resource_id); +#endif + + // Sets an Extension object that can handle theme resource requests. + void SetThemeExtension(const Extension& e); + + private: + // We define a DataHandle typedef to abstract across how data is stored + // across platforms. +#if defined(OS_WIN) + // Windows stores resources in DLLs, which are managed by HINSTANCE. + typedef HINSTANCE DataHandle; +#elif defined(OS_LINUX) || defined(OS_MACOSX) + // Linux uses base::DataPack. + typedef base::DataPack* DataHandle; +#endif + + // Ctor/dtor are private, since we're a singleton. + ResourceBundle(); + ~ResourceBundle(); + + // Free skia_images_. + void FreeImages(); + + // Try to load the main resources and the locale specific strings from an + // external data module. + void LoadResources(const std::wstring& pref_locale); + + // Initialize all the ChromeFont members if they haven't yet been initialized. + void LoadFontsIfNecessary(); + + // Returns the full pathname of the locale file to load. May return an empty + // string if no locale data files are found. + FilePath GetLocaleFilePath(const std::wstring& pref_locale); + + // Loads the raw bytes of a resource from |module| into |bytes|, + // without doing any processing or interpretation of + // the resource. Returns whether we successfully read the resource. + static bool LoadResourceBytes(DataHandle module, + int resource_id, + std::vector<unsigned char>* bytes); + + // Creates and returns a new SkBitmap given the data file to look in and the + // resource id. It's up to the caller to free the returned bitmap when + // done. + static SkBitmap* LoadBitmap(DataHandle dll_inst, int resource_id); + + // Class level lock. Used to protect internal data structures that may be + // accessed from other threads (e.g., skia_images_). + Lock lock_; + + // Handles for data sources. + DataHandle resources_data_; + DataHandle locale_resources_data_; + DataHandle theme_data_; + + // Cached images. The ResourceBundle caches all retrieved bitmaps and keeps + // ownership of the pointers. + typedef std::map<int, SkBitmap*> SkImageMap; + SkImageMap skia_images_; +#if defined(OS_LINUX) + typedef std::map<int, GdkPixbuf*> GdkPixbufMap; + GdkPixbufMap gdk_pixbufs_; +#endif + + // The various fonts used. Cached to avoid repeated GDI creation/destruction. + scoped_ptr<ChromeFont> base_font_; + scoped_ptr<ChromeFont> small_font_; + scoped_ptr<ChromeFont> medium_font_; + scoped_ptr<ChromeFont> medium_bold_font_; + scoped_ptr<ChromeFont> large_font_; + scoped_ptr<ChromeFont> web_font_; + + static ResourceBundle* g_shared_instance_; + + scoped_ptr<Extension> theme_extension_; + + DISALLOW_EVIL_CONSTRUCTORS(ResourceBundle); +}; + +#endif // CHROME_COMMON_RESOURCE_BUNDLE_H__ 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; + } +} diff --git a/app/resource_bundle_mac.mm b/app/resource_bundle_mac.mm new file mode 100644 index 0000000..d24271c --- /dev/null +++ b/app/resource_bundle_mac.mm @@ -0,0 +1,120 @@ +// 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" + +#import <Foundation/Foundation.h> + +#include "base/base_paths.h" +#include "base/data_pack.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/mac_util.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/l10n_util.h" + + +ResourceBundle::~ResourceBundle() { + FreeImages(); + + delete locale_resources_data_; + locale_resources_data_ = NULL; + delete theme_data_; + theme_data_ = NULL; + delete resources_data_; + resources_data_ = NULL; +} + +namespace { + +base::DataPack *LoadResourceDataPack(NSString *name) { + base::DataPack *resource_pack = NULL; + + NSString *resource_path = [mac_util::MainAppBundle() pathForResource:name + ofType:@"pak"]; + if (resource_path) { + FilePath resources_pak_path([resource_path fileSystemRepresentation]); + resource_pack = new base::DataPack; + bool success = resource_pack->Load(resources_pak_path); + if (!success) { + delete resource_pack; + resource_pack = NULL; + } + } + + return resource_pack; +} + +} // namespace + +void ResourceBundle::LoadResources(const std::wstring& pref_locale) { + DLOG_IF(WARNING, pref_locale.size() != 0) + << "ignoring requested locale in favor of NSBundle's selection"; + + DCHECK(resources_data_ == NULL) << "resource data already loaded!"; + resources_data_ = LoadResourceDataPack(@"chrome"); + DCHECK(resources_data_) << "failed to load chrome.pak"; + + DCHECK(locale_resources_data_ == NULL) << "locale data already loaded!"; + locale_resources_data_ = LoadResourceDataPack(@"locale"); + DCHECK(locale_resources_data_) << "failed to load locale.pak"; +} + +void ResourceBundle::LoadThemeResources() { + DCHECK(theme_data_ == NULL) << "theme data already loaded!"; + theme_data_ = LoadResourceDataPack(@"theme"); + DCHECK(theme_data_) << "failed to load theme.pak"; +} + +/* 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; +} diff --git a/app/resource_bundle_win.cc b/app/resource_bundle_win.cc new file mode 100644 index 0000000..dff34c8 --- /dev/null +++ b/app/resource_bundle_win.cc @@ -0,0 +1,157 @@ +// 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 <atlbase.h> + +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/resource_util.h" +#include "base/string_piece.h" +#include "base/win_util.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/l10n_util.h" + +namespace { + +// Returns the flags that should be passed to LoadLibraryEx. +DWORD GetDataDllLoadFlags() { + if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) + return LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE; + + return DONT_RESOLVE_DLL_REFERENCES; +} + +} // end anonymous namespace + +ResourceBundle::~ResourceBundle() { + FreeImages(); + + if (locale_resources_data_) { + BOOL rv = FreeLibrary(locale_resources_data_); + DCHECK(rv); + } + if (theme_data_) { + BOOL rv = FreeLibrary(theme_data_); + DCHECK(rv); + } +} + +void ResourceBundle::LoadResources(const std::wstring& pref_locale) { + // As a convenience, set resources_data_ to the current module. + resources_data_ = _AtlBaseModule.GetModuleInstance(); + + DCHECK(NULL == locale_resources_data_) << "locale dll 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; + } + + // The dll should only have resources, not executable code. + locale_resources_data_ = LoadLibraryEx(locale_path.value().c_str(), NULL, + GetDataDllLoadFlags()); + DCHECK(locale_resources_data_ != NULL) << + "unable to load generated resources"; +} + +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(app_locale + L".dll"); +} + +void ResourceBundle::LoadThemeResources() { + DCHECK(NULL == theme_data_) << "theme dll already loaded"; + std::wstring theme_data_path; + PathService::Get(chrome::DIR_THEMES, &theme_data_path); + file_util::AppendToPath(&theme_data_path, L"default.dll"); + + // The dll should only have resources, not executable code. + theme_data_ = LoadLibraryEx(theme_data_path.c_str(), NULL, + GetDataDllLoadFlags()); + DCHECK(theme_data_ != NULL) << "unable to load " << theme_data_path; +} + +/* static */ +bool ResourceBundle::LoadResourceBytes( + DataHandle module, + int resource_id, + std::vector<unsigned char>* bytes) { + void* data_ptr; + size_t data_size; + if (base::GetDataResourceFromModule(module, resource_id, &data_ptr, + &data_size)) { + bytes->resize(data_size); + memcpy(&(bytes->front()), data_ptr, data_size); + return true; + } else { + return false; + } +} + +HICON ResourceBundle::LoadThemeIcon(int icon_id) { + return ::LoadIcon(theme_data_, MAKEINTRESOURCE(icon_id)); +} + +StringPiece ResourceBundle::GetRawDataResource(int resource_id) { + void* data_ptr; + size_t data_size; + if (base::GetDataResourceFromModule(_AtlBaseModule.GetModuleInstance(), + resource_id, + &data_ptr, + &data_size)) { + return StringPiece(static_cast<const char*>(data_ptr), data_size); + } else if (locale_resources_data_ && + base::GetDataResourceFromModule(locale_resources_data_, + resource_id, + &data_ptr, + &data_size)) { + return StringPiece(static_cast<const char*>(data_ptr), data_size); + } + return StringPiece(); +} + +// Loads and returns a cursor from the current module. +HCURSOR ResourceBundle::LoadCursor(int cursor_id) { + return ::LoadCursor(_AtlBaseModule.GetModuleInstance(), + MAKEINTRESOURCE(cursor_id)); +} + +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(); + } + + DCHECK(IS_INTRESOURCE(message_id)); + + // Get a reference directly to the string resource. + HINSTANCE hinstance = locale_resources_data_; + const ATLSTRINGRESOURCEIMAGE* image = AtlGetStringResourceImage(hinstance, + message_id); + if (!image) { + // Fall back on the current module (shouldn't be any strings here except + // in unittests). + image = AtlGetStringResourceImage(_AtlBaseModule.GetModuleInstance(), + message_id); + if (!image) { + NOTREACHED() << "unable to find resource: " << message_id; + return std::wstring(); + } + } + // Copy into a string16 and return. + return string16(image->achString, image->nLength); +} |