summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorgman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-17 22:25:08 +0000
committergman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-17 22:25:08 +0000
commit523b2523c1f2cb22f56be9cc52fb734370992387 (patch)
treeede3f93c4e118e840778e39b5633d6bfc7058ab3 /o3d
parent9521c61f5588480d8cd6134144db7137630f2529 (diff)
downloadchromium_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')
-rw-r--r--o3d/core/cross/bitmap.cc53
-rw-r--r--o3d/core/cross/file_request.h15
-rw-r--r--o3d/import/cross/raw_data.cc81
-rw-r--r--o3d/import/cross/raw_data.h9
-rw-r--r--o3d/import/cross/raw_data_test.cc74
-rw-r--r--o3d/plugin/cross/async_loading.cc68
-rw-r--r--o3d/plugin/cross/async_loading.h6
-rw-r--r--o3d/plugin/idl/file_request.idl7
-rw-r--r--o3d/plugin/idl/pack.idl7
9 files changed, 281 insertions, 39 deletions
diff --git a/o3d/core/cross/bitmap.cc b/o3d/core/cross/bitmap.cc
index 61ac355..320d3e1 100644
--- a/o3d/core/cross/bitmap.cc
+++ b/o3d/core/cross/bitmap.cc
@@ -219,40 +219,39 @@ bool Bitmap::LoadFromStream(MemoryReadStream *stream,
bool Bitmap::LoadFromFile(const FilePath &filepath,
ImageFileType file_type,
bool generate_mipmaps) {
- // Open the file
+ // Open the file.
+ bool result = false;
String filename = FilePathToUTF8(filepath);
FILE *file = OpenFile(filepath, "rb");
if (!file) {
DLOG(ERROR) << "bitmap file not found \"" << filename << "\"";
- return false;
- }
-
- // Determine the file's length
- int64 file_size64;
- if (!GetFileSize(filepath, &file_size64)) {
- DLOG(ERROR) << "error getting bitmap file size \"" << filename << "\"";
+ } else {
+ // Determine the file's length
+ int64 file_size64;
+ if (!GetFileSize(filepath, &file_size64)) {
+ DLOG(ERROR) << "error getting bitmap file size \"" << filename << "\"";
+ } else {
+ if (file_size64 > 0xffffffffLL) {
+ DLOG(ERROR) << "bitmap file is too large \"" << filename << "\"";
+ } else {
+ size_t file_length = static_cast<size_t>(file_size64);
+
+ // Load the compressed image data into memory
+ MemoryBuffer<uint8> file_contents(file_length);
+ uint8 *p = file_contents;
+ if (fread(p, file_length, 1, file) != 1) {
+ DLOG(ERROR) << "error reading bitmap file \"" << filename << "\"";
+ } else {
+ // And create the bitmap from a memory stream
+ MemoryReadStream stream(file_contents, file_length);
+ result = LoadFromStream(&stream, filename, file_type,
+ generate_mipmaps);
+ }
+ }
+ }
CloseFile(file);
- return false;
- }
- if (file_size64 > 0xffffffffLL) {
- DLOG(ERROR) << "bitmap file is too large \"" << filename << "\"";
- return false;
}
- size_t file_length = static_cast<size_t>(file_size64);
-
- // Load the compressed image data into memory
- MemoryBuffer<uint8> file_contents(file_length);
- uint8 *p = file_contents;
- if (fread(p, file_length, 1, file) != 1) {
- DLOG(ERROR) << "error reading bitmap file \"" << filename << "\"";
- return false;
- }
-
- // And create the bitmap from a memory stream
- MemoryReadStream stream(file_contents, file_length);
- bool result = LoadFromStream(&stream, filename, file_type, generate_mipmaps);
- CloseFile(file);
return result;
}
diff --git a/o3d/core/cross/file_request.h b/o3d/core/cross/file_request.h
index 1311ed1..11e695d9 100644
--- a/o3d/core/cross/file_request.h
+++ b/o3d/core/cross/file_request.h
@@ -42,6 +42,7 @@
#include "core/cross/callback.h"
#include "core/cross/object_base.h"
#include "core/cross/pack.h"
+#include "import/cross/raw_data.h"
namespace o3d {
@@ -54,7 +55,8 @@ class FileRequest : public ObjectBase {
enum Type {
TYPE_INVALID,
TYPE_TEXTURE,
- TYPE_MAX = TYPE_TEXTURE,
+ TYPE_RAWDATA,
+ TYPE_MAX = TYPE_RAWDATA,
};
enum ReadyState { // These are copied from XMLHttpRequest.
@@ -82,6 +84,9 @@ class FileRequest : public ObjectBase {
if (type == "texture") {
return TYPE_TEXTURE;
}
+ if (type == "rawdata") {
+ return TYPE_RAWDATA;
+ }
return TYPE_INVALID;
}
@@ -109,6 +114,9 @@ class FileRequest : public ObjectBase {
Texture *texture() const {
return texture_.Get();
}
+ RawData *data() const {
+ return data_.Get();
+ }
bool generate_mipmaps() const { return generate_mipmaps_; }
void set_generate_mipmaps(bool value) {
generate_mipmaps_ = value;
@@ -117,6 +125,10 @@ class FileRequest : public ObjectBase {
CHECK(type_ == TYPE_TEXTURE);
texture_ = Texture::Ref(texture);
}
+ void set_data(RawData *data) {
+ CHECK(type_ == TYPE_RAWDATA);
+ data_ = RawData::Ref(data);
+ }
bool done() const {
return done_;
}
@@ -153,6 +165,7 @@ class FileRequest : public ObjectBase {
String uri_;
Type type_;
Texture::Ref texture_; // Only used on a successful texture load.
+ RawData::Ref data_; // Only used on a successful RawData load.
bool generate_mipmaps_;
bool done_; // Set after completion/failure to indicate success_ is valid.
bool success_; // Set after completion/failure to indicate which it is.
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 {
diff --git a/o3d/plugin/cross/async_loading.cc b/o3d/plugin/cross/async_loading.cc
index bcd8333..f38ef5d 100644
--- a/o3d/plugin/cross/async_loading.cc
+++ b/o3d/plugin/cross/async_loading.cc
@@ -41,6 +41,7 @@
#include "core/cross/file_request.h"
#include "core/cross/pack.h"
#include "core/cross/texture.h"
+#include "import/cross/raw_data.h"
namespace glue {
namespace namespace_o3d {
@@ -49,6 +50,7 @@ namespace class_FileRequest {
using _o3d::PluginObject;
using o3d::Bitmap;
using o3d::Pack;
+using o3d::RawData;
using o3d::Texture;
// StreamManager::FinishedCallback
@@ -124,6 +126,69 @@ class LoadTextureURLCallback : public StreamManager::FinishedCallback {
}
};
+// StreamManager::FinishedCallback
+// implementation that imports the file as a RawData once downloaded. When the
+// download completes, LoadRawDataURLCallback::Run() will be called, which will
+// parse and load the downloaded file. After that load is complete,
+// onreadystatechange will be run to notify the user.
+class LoadRawDataURLCallback : public StreamManager::FinishedCallback {
+ public:
+ // Creates a new LoadRawDataURLCallback.
+ static LoadRawDataURLCallback *Create(FileRequest *request) {
+ return new LoadRawDataURLCallback(request);
+ }
+
+ virtual ~LoadRawDataURLCallback() {
+ // If the file request was interrupted (for example we moved to a new page
+ // before the file transfer was completed) then we tell the FileRequest
+ // object that the request failed. It's important to call this here since
+ // set_success() will release the pack reference that the FileRequest holds
+ // which will allow the pack to be garbage collected.
+ if (!request_->done()) {
+ request_->set_success(false);
+ }
+ }
+
+ // Loads the RawData file, calls the JS callback to pass back the RawData
+ // object.
+ virtual void Run(DownloadStream*,
+ bool success,
+ const std::string &filename,
+ const std::string &mime_type) {
+ RawData::Ref data;
+ if (success) {
+ o3d::ErrorCollector error_collector(request_->service_locator());
+ request_->set_ready_state(FileRequest::STATE_LOADED);
+ data = RawData::Ref(RawData::CreateFromFile(request_->service_locator(),
+ request_->uri(),
+ filename));
+ if (data) {
+ request_->set_data(data);
+ } else {
+ success = false;
+ }
+ request_->set_error(error_collector.errors());
+ } else {
+ // No error is passed in from the stream but we MUST have an error
+ // for the request to work on the javascript side.
+ request_->set_error("Could not download: " + request_->uri());
+ }
+ request_->set_success(success);
+ // Since the standard codes only go far enough to tell us that the download
+ // succeeded, we set the success [and implicitly the done] flags to give the
+ // rest of the story.
+ if (request_->onreadystatechange())
+ request_->onreadystatechange()->Run();
+ }
+
+ private:
+ FileRequest::Ref request_;
+
+ explicit LoadRawDataURLCallback(FileRequest *request)
+ : request_(request) {
+ }
+};
+
// Sets up the parameters required for all FileRequests.
void userglue_method_open(void *plugin_data,
FileRequest *request,
@@ -183,6 +248,9 @@ void userglue_method_send(void *plugin_data,
case FileRequest::TYPE_TEXTURE:
callback = LoadTextureURLCallback::Create(request);
break;
+ case FileRequest::TYPE_RAWDATA:
+ callback = LoadRawDataURLCallback::Create(request);
+ break;
default:
CHECK(false);
}
diff --git a/o3d/plugin/cross/async_loading.h b/o3d/plugin/cross/async_loading.h
index d0df9df..b64175e 100644
--- a/o3d/plugin/cross/async_loading.h
+++ b/o3d/plugin/cross/async_loading.h
@@ -32,8 +32,8 @@
// This file declares the glue for FileRequest actions.
-#ifndef EXPERIMENTAL_O3D_O3DPLUGIN_AUTOGEN_O3D_GLUE_ASYNC_LOADING_H_
-#define EXPERIMENTAL_O3D_O3DPLUGIN_AUTOGEN_O3D_GLUE_ASYNC_LOADING_H_
+#ifndef O3D_PLUGIN_CROSS_ASYNC_LOADING_H_
+#define O3D_PLUGIN_CROSS_ASYNC_LOADING_H_
#include "core/cross/callback.h"
#include "core/cross/types.h"
@@ -64,4 +64,4 @@ void userglue_method_send(void *plugin_data,
} // namespace namespace_o3d
} // namespace glue
-#endif // EXPERIMENTAL_O3D_O3DPLUGIN_AUTOGEN_O3D_GLUE_ASYNC_LOADING_H_
+#endif // O3D_PLUGIN_CROSS_ASYNC_LOADING_H_
diff --git a/o3d/plugin/idl/file_request.idl b/o3d/plugin/idl/file_request.idl
index 5e931ce..5b1c9a3 100644
--- a/o3d/plugin/idl/file_request.idl
+++ b/o3d/plugin/idl/file_request.idl
@@ -76,6 +76,13 @@ namespace o3d {
texture.
%]
[getter=texture] Texture? texture;
+
+ %[
+ On completion of successful RawData file loads, this holds the loaded
+ RawData.
+ %]
+ [getter=data] RawData? data;
+
%[
Whether or not to generate mip-maps on textures that are loaded (default:
true). Mip-maps are not generated for DXTC textures. DDS files can contain
diff --git a/o3d/plugin/idl/pack.idl b/o3d/plugin/idl/pack.idl
index 0c9cba7..94f8e0e 100644
--- a/o3d/plugin/idl/pack.idl
+++ b/o3d/plugin/idl/pack.idl
@@ -270,8 +270,11 @@ typedef ObjectBase[] ObjectArray;
[userglue_getter, getter] ObjectBaseArray objects_;
%[
- Creates a FileRequest to be used to asynchronously load a Texture.
- \param type Must be "TEXTURE"
+ Creates a FileRequest to be used to asynchronously load a Texture or
+ RawData. Note: Loading a "TEXTURE" is deprecated. The recommended way to
+ load a texture is to load a RawData, use that to create Bitmap, Massage
+ the Bitmap to your liking the use that to create a Texture.
+ \param type Must be "TEXTURE" or "RAWDATA"
\return a FileRequest
%]
[noccp, userglue] FileRequest? CreateFileRequest(String type);