diff options
author | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-17 22:25:08 +0000 |
---|---|---|
committer | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-17 22:25:08 +0000 |
commit | 523b2523c1f2cb22f56be9cc52fb734370992387 (patch) | |
tree | ede3f93c4e118e840778e39b5633d6bfc7058ab3 /o3d/import | |
parent | 9521c61f5588480d8cd6134144db7137630f2529 (diff) | |
download | chromium_src-523b2523c1f2cb22f56be9cc52fb734370992387.zip chromium_src-523b2523c1f2cb22f56be9cc52fb734370992387.tar.gz chromium_src-523b2523c1f2cb22f56be9cc52fb734370992387.tar.bz2 |
Add RawData request in preparation for manual loading of
Bitmaps and being able to flip them, scale them, etc...
Basically this just makes it possible to download a RawData
directly which you can then pass you'll be able to pass to
pack->CreateBitmapFromRawData.
Some design comments:
I used SetFromFile instead of making a different constructor
since it seemed wrong to do file IO in a constructor. Given
that SetFromFile is private I don't think this is a problem
since you can't call it directly.
Also, I thought about loading the file first and then calling
the original constructor but it seemed like a waste to load
the file into memory, then copy it to a new buffer when I could
just load it directly.
Finally I made it take a String instead of a FilePath because
it meant other places had to do less work.
Review URL: http://codereview.chromium.org/149784
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21015 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/import')
-rw-r--r-- | o3d/import/cross/raw_data.cc | 81 | ||||
-rw-r--r-- | o3d/import/cross/raw_data.h | 9 | ||||
-rw-r--r-- | o3d/import/cross/raw_data_test.cc | 74 |
3 files changed, 158 insertions, 6 deletions
diff --git a/o3d/import/cross/raw_data.cc b/o3d/import/cross/raw_data.cc index 53039c2..deabe37 100644 --- a/o3d/import/cross/raw_data.cc +++ b/o3d/import/cross/raw_data.cc @@ -35,6 +35,9 @@ #include "import/cross/raw_data.h" #include "base/file_util.h" +#include "utils/cross/file_path_utils.h" +#include "base/file_path.h" +#include "base/file_util.h" #ifdef OS_MACOSX #include <CoreFoundation/CoreFoundation.h> @@ -44,6 +47,10 @@ #include <rpc.h> #endif +using file_util::OpenFile; +using file_util::CloseFile; +using file_util::GetFileSize; + namespace o3d { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -59,7 +66,7 @@ RawData::RawData(ServiceLocator* service_locator, const String &uri, const void *data, size_t length) - : ParamObject(service_locator), uri_(uri) { + : ParamObject(service_locator), uri_(uri), allow_string_value_(true) { // make private copy of data data_.reset(new uint8[length]); length_ = length; @@ -74,6 +81,17 @@ RawData::Ref RawData::Create(ServiceLocator* service_locator, return RawData::Ref(new RawData(service_locator, uri, data, length)); } +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RawData::Ref RawData::CreateFromFile(ServiceLocator* service_locator, + const String &uri, + const String& filename) { + RawData::Ref data(Create(service_locator, uri, NULL, 0)); + if (!data->SetFromFile(filename)) { + data.Reset(); + } + + return data; +} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RawData::~RawData() { @@ -81,6 +99,46 @@ RawData::~RawData() { } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool RawData::SetFromFile(const String& filename) { + // We can't allow general string files to be downloaded from anywhere + // as that would override the security measures that have been added to + // XMLHttpRequest over the years. Images and other binary datas are okay. + // because RawData can only be passed to stuff that understands specific + // formats. + allow_string_value_ = false; + FilePath filepath = UTF8ToFilePath(filename); + FILE *file = OpenFile(filepath, "rb"); + bool result = false; + if (!file) { + DLOG(ERROR) << "file not found \"" << filename << "\""; + } else { + // Determine the file's length + int64 file_size64; + if (!GetFileSize(filepath, &file_size64)) { + DLOG(ERROR) << "error getting file size \"" << filename << "\""; + } else { + if (file_size64 > 0xffffffffLL) { + DLOG(ERROR) << "file is too large \"" << filename << "\""; + } else { + size_t file_length = static_cast<size_t>(file_size64); + + // Load the file data into memory + data_.reset(new uint8[file_length]); + length_ = file_length; + if (fread(data_.get(), file_length, 1, file) != 1) { + DLOG(ERROR) << "error reading file \"" << filename << "\""; + } else { + result = true; + } + } + } + CloseFile(file); + } + + return result; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const uint8 *RawData::GetData() const { // Return data immediately if we have it if (data_.get()) { @@ -195,12 +253,23 @@ String RawData::StringValue() const { // .json, .xml, .ini, .csv, .php, .js, .html, .css .xsl, .dae, etc.) So, // instead we validate the string is valid UTF-8 AND that there are no NULLs // in the string. - size_t length; - const char* utf8 = GetValidUTF8(*this, &length); - if (!utf8) { - O3D_ERROR(service_locator()) << "RawData is not valid UTF-8 string"; + + // We can't allow general string files to be downloaded from anywhere + // as that would override the security measures that have been added to + // XMLHttpRequest over the years. Images and other binary datas are okay. + // because RawData can only be passed to stuff that understands specific + // formats. + if (!allow_string_value_) { + O3D_ERROR(service_locator()) + << "You can only get a stringValue from RawDatas inside archives."; } else { - return String (utf8, length); + size_t length; + const char* utf8 = GetValidUTF8(*this, &length); + if (!utf8) { + O3D_ERROR(service_locator()) << "RawData is not valid UTF-8 string"; + } else { + return String (utf8, length); + } } return String(); } diff --git a/o3d/import/cross/raw_data.h b/o3d/import/cross/raw_data.h index 8012efd..1929b1a 100644 --- a/o3d/import/cross/raw_data.h +++ b/o3d/import/cross/raw_data.h @@ -46,6 +46,8 @@ #include "core/cross/param.h" #include "core/cross/types.h" +class FilePath; + namespace o3d { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -58,6 +60,10 @@ class RawData : public ParamObject { const void *data, size_t length); + static RawData::Ref CreateFromFile(ServiceLocator* service_locator, + const String &uri, + const String& filename); + virtual ~RawData(); const uint8 *GetData() const; @@ -94,6 +100,7 @@ class RawData : public ParamObject { mutable scoped_array<uint8> data_; size_t length_; FilePath temp_filepath_; + bool allow_string_value_; // Deletes temp file if it exists void DeleteTempFile(); @@ -103,6 +110,8 @@ class RawData : public ParamObject { const void *data, size_t length); + bool SetFromFile(const String& filename); + friend class IClassManager; friend class Pack; diff --git a/o3d/import/cross/raw_data_test.cc b/o3d/import/cross/raw_data_test.cc index b1ccc5dd..4ab0955 100644 --- a/o3d/import/cross/raw_data_test.cc +++ b/o3d/import/cross/raw_data_test.cc @@ -34,14 +34,42 @@ #include "core/cross/client.h" #include "tests/common/win/testing_common.h" +#include "utils/cross/file_path_utils.h" +#include "base/file_path.h" +#include "base/file_util.h" #include "core/cross/error.h" +#include "core/cross/error_status.h" #include "import/cross/memory_buffer.h" #include "import/cross/raw_data.h" +using file_util::OpenFile; +using file_util::CloseFile; +using file_util::GetFileSize; + namespace o3d { +namespace { + +// Checks if an error has occured on the client then clears the error. +bool CheckErrorExists(IErrorStatus* error_status) { + bool have_error = !error_status->GetLastError().empty(); + error_status->ClearLastError(); + return have_error; +} + +} // anonymous namespace + // Test fixture for RawData testing. class RawDataTest : public testing::Test { + protected: + RawDataTest() + : error_status_(g_service_locator) { + } + + IErrorStatus* error_status() { return &error_status_; } + + private: + ErrorStatus error_status_; }; // Test RawData @@ -75,6 +103,52 @@ TEST_F(RawDataTest, Basic) { ASSERT_EQ(raw_data->uri(), uri); } +TEST_F(RawDataTest, CreateFromFile) { + String uri("test_filename"); + String filename = *g_program_path + "/bitmap_test/tga-256x256-24bit.tga"; + RawData::Ref ref = RawData::CreateFromFile(g_service_locator, + uri, + filename); + ASSERT_FALSE(ref.IsNull()); + FilePath filepath = UTF8ToFilePath(filename); + FILE *file = OpenFile(filepath, "rb"); + ASSERT_TRUE(file != NULL); + int64 file_size64; + ASSERT_TRUE(GetFileSize(filepath, &file_size64)); + size_t file_length = static_cast<size_t>(file_size64); + ASSERT_TRUE(file_length > 0); + scoped_array<uint8> data(new uint8[file_length]); + ASSERT_EQ(fread(data.get(), file_length, 1, file), 1); + CloseFile(file); + + ASSERT_EQ(file_length, ref->GetLength()); + ASSERT_EQ(0, memcmp(ref->GetData(), data.get(), file_length)); +} + +TEST_F(RawDataTest, CreateFromFileFail) { + String uri("test_filename"); + String filename = *g_program_path + "/bitmap_test/non-existent-file.foo"; + RawData::Ref ref = RawData::CreateFromFile(g_service_locator, + uri, + filename); + ASSERT_TRUE(ref.IsNull()); +} + +TEST_F(RawDataTest, CreateFromFileStringValue) { + String uri("test_filename"); + String filename = *g_program_path + "/unittest_data/fur.fx"; + RawData::Ref ref = RawData::CreateFromFile(g_service_locator, + uri, + filename); + ASSERT_FALSE(ref.IsNull()); + EXPECT_TRUE(ref->GetLength() > 0); + EXPECT_FALSE(CheckErrorExists(error_status())); + // We should NOT be able to get a string value from an individually + // loaded RawData. + EXPECT_TRUE(ref->StringValue().empty()); + EXPECT_TRUE(CheckErrorExists(error_status())); +} + namespace { struct TestData { |