diff options
author | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-27 18:29:24 +0000 |
---|---|---|
committer | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-27 18:29:24 +0000 |
commit | 22339b123c68805c7c293c67f6f47ea45f0fd1a1 (patch) | |
tree | bb05e2e3eb0362338e921a4dce9d5c350437326e /webkit/blob | |
parent | e840afdedd33728491639312a268fbf37a48f078 (diff) | |
download | chromium_src-22339b123c68805c7c293c67f6f47ea45f0fd1a1.zip chromium_src-22339b123c68805c7c293c67f6f47ea45f0fd1a1.tar.gz chromium_src-22339b123c68805c7c293c67f6f47ea45f0fd1a1.tar.bz2 |
Support sending BlobData to browser process. Also support sending UploadData
with the blob info to browser process.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/3108042
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57707 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/blob')
-rw-r--r-- | webkit/blob/blob_data.cc | 62 | ||||
-rw-r--r-- | webkit/blob/blob_data.h | 196 | ||||
-rw-r--r-- | webkit/blob/blob_storage_controller.cc | 117 | ||||
-rw-r--r-- | webkit/blob/blob_storage_controller.h | 43 | ||||
-rw-r--r-- | webkit/blob/blob_storage_controller_unittest.cc | 85 | ||||
-rw-r--r-- | webkit/blob/webkit_blob.gypi | 31 |
6 files changed, 534 insertions, 0 deletions
diff --git a/webkit/blob/blob_data.cc b/webkit/blob/blob_data.cc new file mode 100644 index 0000000..d72750e --- /dev/null +++ b/webkit/blob/blob_data.cc @@ -0,0 +1,62 @@ +// Copyright (c) 2010 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 "webkit/blob/blob_data.h" + +#include "base/logging.h" +#include "base/time.h" +#include "third_party/WebKit/WebKit/chromium/public/WebBlobData.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCString.h" +#include "third_party/WebKit/WebKit/chromium/public/WebData.h" +#include "webkit/glue/webkit_glue.h" + +using WebKit::WebBlobData; +using WebKit::WebData; +using WebKit::WebString; + +namespace { + +// Time::FromDoubleT() does not return empty Time object when dt is 0. +// We have to work around this problem here. +base::Time DoubleTToTime(double dt) { + return dt ? base::Time::FromDoubleT(dt) : base::Time(); +} + +} + +namespace webkit_blob { + +BlobData::BlobData(const WebBlobData& data) { + size_t i = 0; + WebBlobData::Item item; + while (data.itemAt(i++, item)) { + switch (item.type) { + case WebBlobData::Item::TypeData: + if (!item.data.isEmpty()) + AppendData(item.data); + break; + case WebBlobData::Item::TypeFile: + AppendFile( + webkit_glue::WebStringToFilePath(item.filePath), + static_cast<uint64>(item.offset), + static_cast<uint64>(item.length), + DoubleTToTime(item.expectedModificationTime)); + break; + case WebBlobData::Item::TypeBlob: + if (item.length) { + AppendBlob( + item.blobURL, + static_cast<uint64>(item.offset), + static_cast<uint64>(item.length)); + } + break; + default: + NOTREACHED(); + } + } + content_type_= data.contentType().utf8().data(); + content_disposition_ = data.contentDisposition().utf8().data(); +} + +} // namespace webkit_blob diff --git a/webkit/blob/blob_data.h b/webkit/blob/blob_data.h new file mode 100644 index 0000000..96f4011 --- /dev/null +++ b/webkit/blob/blob_data.h @@ -0,0 +1,196 @@ +// Copyright (c) 2010 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 WEBKIT_BLOB_BLOB_DATA_H_ +#define WEBKIT_BLOB_BLOB_DATA_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/ref_counted.h" +#include "base/time.h" +#include "googleurl/src/gurl.h" + +namespace WebKit { +class WebBlobData; +} + +namespace webkit_blob { + +class BlobData : public base::RefCounted<BlobData> { + public: + enum Type { + TYPE_DATA, + TYPE_FILE, + TYPE_BLOB + }; + + class Item { + public: + Item() + : type_(TYPE_DATA), + offset_(0), + length_(0) { + } + + Type type() const { return type_; } + const std::string& data() const { return data_; } + const FilePath& file_path() const { return file_path_; } + const GURL& blob_url() const { return blob_url_; } + uint64 offset() const { return offset_; } + uint64 length() const { return length_; } + const base::Time& expected_modification_time() const { + return expected_modification_time_; + } + + void SetToData(const std::string& data) { + SetToData(data, 0, static_cast<uint32>(data.size())); + } + + void SetToData(const std::string& data, uint32 offset, uint32 length) { + // TODO(jianli): Need to implement ref-counting vector storage. + type_ = TYPE_DATA; + data_ = data; + offset_ = offset; + length_ = length; + } + + void SetToFile(const FilePath& file_path, uint64 offset, uint64 length, + const base::Time& expected_modification_time) { + type_ = TYPE_FILE; + file_path_ = file_path; + offset_ = offset; + length_ = length; + expected_modification_time_ = expected_modification_time; + } + + void SetToBlob(const GURL& blob_url, uint64 offset, uint64 length) { + type_ = TYPE_BLOB; + blob_url_ = blob_url; + offset_ = offset; + length_ = length; + } + +#if defined(UNIT_TEST) + bool operator==(const Item& other) const { + if (type_ != other.type_) + return false; + if (type_ == TYPE_DATA) { + return data_ == other.data_ && + offset_ == other.offset_ && + length_ == other.length_; + } + if (type_ == TYPE_FILE) { + return file_path_ == other.file_path_ && + offset_ == other.offset_ && + length_ == other.length_ && + expected_modification_time_ == other.expected_modification_time_; + } + if (type_ == TYPE_BLOB) { + return blob_url_ == other.blob_url_ && + offset_ == other.offset_ && + length_ == other.length_; + } + return false; + } + + bool operator!=(const Item& other) const { + return !(*this == other); + } +#endif // defined(UNIT_TEST) + + private: + Type type_; + + // For Data type. + std::string data_; + + // For File type. + FilePath file_path_; + + // For Blob typ. + GURL blob_url_; + + uint64 offset_; + uint64 length_; + base::Time expected_modification_time_; + }; + + BlobData() { } + explicit BlobData(const WebKit::WebBlobData& data); + + void AppendData(const std::string& data) { + // TODO(jianli): Consider writing the big data to the disk. + AppendData(data, 0, static_cast<uint32>(data.size())); + } + + void AppendData(const std::string& data, uint32 offset, uint32 length) { + if (length > 0) { + items_.push_back(Item()); + items_.back().SetToData(data, offset, length); + } + } + + void AppendFile(const FilePath& file_path, uint64 offset, uint64 length, + const base::Time& expected_modification_time) { + items_.push_back(Item()); + items_.back().SetToFile(file_path, offset, length, + expected_modification_time); + } + + void AppendBlob(const GURL& blob_url, uint64 offset, uint64 length) { + items_.push_back(Item()); + items_.back().SetToBlob(blob_url, offset, length); + } + + const std::vector<Item>& items() const { return items_; } + void set_items(const std::vector<Item>& items) { + items_ = items; + } + void swap_items(std::vector<Item>* items) { + items_.swap(*items); + } + + const std::string& content_type() const { return content_type_; } + void set_content_type(const std::string& content_type) { + content_type_ = content_type; + } + + const std::string& content_disposition() const { + return content_disposition_; + } + void set_content_disposition(const std::string& content_disposition) { + content_disposition_ = content_disposition; + } + +#if defined(UNIT_TEST) + bool operator==(const BlobData& other) const { + if (content_type_ != other.content_type_) + return false; + if (content_disposition_ != other.content_disposition_) + return false; + if (items_.size() != other.items_.size()) + return false; + for (size_t i = 0; i < items_.size(); ++i) { + if (items_[i] != other.items_[i]) + return false; + } + return true; + } +#endif // defined(UNIT_TEST) + + private: + friend class base::RefCounted<BlobData>; + + virtual ~BlobData() { } + + std::string content_type_; + std::string content_disposition_; + std::vector<Item> items_; +}; + +} // namespace webkit_blob + +#endif // WEBKIT_BLOB_BLOB_DATA_H_ diff --git a/webkit/blob/blob_storage_controller.cc b/webkit/blob/blob_storage_controller.cc new file mode 100644 index 0000000..b552d10 --- /dev/null +++ b/webkit/blob/blob_storage_controller.cc @@ -0,0 +1,117 @@ +// Copyright (c) 2010 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 "webkit/blob/blob_storage_controller.h" + +#include "base/logging.h" +#include "googleurl/src/gurl.h" +#include "webkit/blob/blob_data.h" + +namespace webkit_blob { + +BlobStorageController::BlobStorageController() { +} + +BlobStorageController::~BlobStorageController() { +} + +void BlobStorageController::AppendStorageItems( + BlobData* target_blob_data, BlobData* src_blob_data, + uint64 offset, uint64 length) { + DCHECK(target_blob_data && src_blob_data && + length != static_cast<uint64>(-1)); + + std::vector<BlobData::Item>::const_iterator iter = + src_blob_data->items().begin(); + if (offset) { + for (; iter != src_blob_data->items().end(); ++iter) { + if (offset >= iter->length()) + offset -= iter->length(); + else + break; + } + } + + for (; iter != src_blob_data->items().end() && length > 0; ++iter) { + uint64 current_length = iter->length() - offset; + uint64 new_length = current_length > length ? length : current_length; + if (iter->type() == BlobData::TYPE_DATA) { + target_blob_data->AppendData(iter->data(), + static_cast<uint32>(iter->offset() + offset), + static_cast<uint32>(new_length)); + } else { + DCHECK(iter->type() == BlobData::TYPE_FILE); + target_blob_data->AppendFile(iter->file_path(), + iter->offset() + offset, + new_length, + iter->expected_modification_time()); + } + length -= new_length; + offset = 0; + } +} + +void BlobStorageController::RegisterBlobUrl( + const GURL& url, const BlobData* blob_data) { + scoped_refptr<BlobData> target_blob_data = new BlobData(); + target_blob_data->set_content_type(blob_data->content_type()); + target_blob_data->set_content_disposition(blob_data->content_disposition()); + + // The blob data is stored in the "canonical" way. That is, it only contains a + // list of Data and File items. + // 1) The Data item is denoted by the raw data and the range. + // 2) The File item is denoted by the file path, the range and the expected + // modification time. + // All the Blob items in the passing blob data are resolved and expanded into + // a set of Data and File items. + + for (std::vector<BlobData::Item>::const_iterator iter = + blob_data->items().begin(); + iter != blob_data->items().end(); ++iter) { + switch (iter->type()) { + case BlobData::TYPE_DATA: + target_blob_data->AppendData(iter->data()); + break; + case BlobData::TYPE_FILE: + target_blob_data->AppendFile(iter->file_path(), + iter->offset(), + iter->length(), + iter->expected_modification_time()); + break; + case BlobData::TYPE_BLOB: { + scoped_refptr<BlobData> src_blob_data = + blob_map_[iter->blob_url().spec()]; + DCHECK(src_blob_data.get()); + if (src_blob_data.get()) + AppendStorageItems(target_blob_data.get(), + src_blob_data.get(), + iter->offset(), + iter->length()); + break; + } + } + } + + blob_map_[url.spec()] = target_blob_data; +} + +void BlobStorageController::RegisterBlobUrlFrom( + const GURL& url, const GURL& src_url) { + BlobData* blob_data = GetBlobDataFromUrl(src_url); + if (!blob_data) + return; + + blob_map_[url.spec()] = blob_data; +} + +void BlobStorageController::UnregisterBlobUrl(const GURL& url) { + blob_map_.erase(url.spec()); +} + +BlobData* BlobStorageController::GetBlobDataFromUrl(const GURL& url) { + return (blob_map_.find(url.spec()) == blob_map_.end()) ? + NULL : blob_map_[url.spec()].get(); +} + +} // namespace webkit_blob diff --git a/webkit/blob/blob_storage_controller.h b/webkit/blob/blob_storage_controller.h new file mode 100644 index 0000000..dd98f18 --- /dev/null +++ b/webkit/blob/blob_storage_controller.h @@ -0,0 +1,43 @@ +// Copyright (c) 2010 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 WEBKIT_BLOB_BLOB_STORAGE_CONTROLLER_H_ +#define WEBKIT_BLOB_BLOB_STORAGE_CONTROLLER_H_ + +#include "base/hash_tables.h" +#include "base/process.h" +#include "base/ref_counted.h" + +class GURL; + +namespace webkit_blob { + +class BlobData; + +// This class handles the logistics of blob Storage within the browser process. +class BlobStorageController { + public: + BlobStorageController(); + ~BlobStorageController(); + + void RegisterBlobUrl(const GURL& url, const BlobData* blob_data); + void RegisterBlobUrlFrom(const GURL& url, const GURL& src_url); + void UnregisterBlobUrl(const GURL& url); + BlobData* GetBlobDataFromUrl(const GURL& url); + + private: + void AppendStorageItems(BlobData* target_blob_data, + BlobData* src_blob_data, + uint64 offset, + uint64 length); + + typedef base::hash_map<std::string, scoped_refptr<BlobData> > BlobMap; + BlobMap blob_map_; + + DISALLOW_COPY_AND_ASSIGN(BlobStorageController); +}; + +} // namespace webkit_blob + +#endif // WEBKIT_BLOB_BLOB_STORAGE_CONTROLLER_H_ diff --git a/webkit/blob/blob_storage_controller_unittest.cc b/webkit/blob/blob_storage_controller_unittest.cc new file mode 100644 index 0000000..3bd0b63 --- /dev/null +++ b/webkit/blob/blob_storage_controller_unittest.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2010 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 "base/file_path.h" +#include "base/time.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/blob/blob_data.h" +#include "webkit/blob/blob_storage_controller.h" + +namespace webkit_blob { + +TEST(BlobStorageControllerTest, RegisterBlobUrl) { + // Setup a set of blob data for testing. + base::Time time1, time2; + base::Time::FromString(L"Tue, 15 Nov 1994, 12:45:26 GMT", &time1); + base::Time::FromString(L"Mon, 14 Nov 1994, 11:30:49 GMT", &time2); + + scoped_refptr<BlobData> blob_data1 = new BlobData(); + blob_data1->AppendData("Data1"); + blob_data1->AppendData("Data2"); + blob_data1->AppendFile(FilePath(FILE_PATH_LITERAL("File1.txt")), + 10, 1024, time1); + + scoped_refptr<BlobData> blob_data2 = new BlobData(); + blob_data2->AppendData("Data3"); + blob_data2->AppendBlob(GURL("blob://url_1"), 8, 100); + blob_data2->AppendFile(FilePath(FILE_PATH_LITERAL("File2.txt")), + 0, 20, time2); + + scoped_refptr<BlobData> canonicalized_blob_data2 = new BlobData(); + canonicalized_blob_data2->AppendData("Data3"); + canonicalized_blob_data2->AppendData("Data2", 3, 2); + canonicalized_blob_data2->AppendFile(FilePath(FILE_PATH_LITERAL("File1.txt")), + 10, 98, time1); + canonicalized_blob_data2->AppendFile(FilePath(FILE_PATH_LITERAL("File2.txt")), + 0, 20, time2); + + scoped_ptr<BlobStorageController> blob_storage_controller( + new BlobStorageController()); + + // Test registering a blob URL referring to the blob data containing only + // data and file. + GURL blob_url1("blob://url_1"); + blob_storage_controller->RegisterBlobUrl(blob_url1, blob_data1); + + BlobData* blob_data_found = + blob_storage_controller->GetBlobDataFromUrl(blob_url1); + ASSERT_TRUE(blob_data_found != NULL); + EXPECT_TRUE(*blob_data_found == *blob_data1); + + // Test registering a blob URL referring to the blob data containing data, + // file and blob. + GURL blob_url2("blob://url_2"); + blob_storage_controller->RegisterBlobUrl(blob_url2, blob_data2); + + blob_data_found = blob_storage_controller->GetBlobDataFromUrl(blob_url2); + ASSERT_TRUE(blob_data_found != NULL); + EXPECT_TRUE(*blob_data_found == *canonicalized_blob_data2); + + // Test registering a blob URL referring to existent blob URL. + GURL blob_url3("blob://url_3"); + blob_storage_controller->RegisterBlobUrlFrom(blob_url3, blob_url1); + + blob_data_found = blob_storage_controller->GetBlobDataFromUrl(blob_url3); + ASSERT_TRUE(blob_data_found != NULL); + EXPECT_TRUE(*blob_data_found == *blob_data1); + + // Test registering a blob URL referring to non-existent blob URL. + GURL nonexistent_blob_url("blob://url_none"); + GURL blob_url4("blob://url_4"); + blob_storage_controller->RegisterBlobUrlFrom(blob_url4, nonexistent_blob_url); + + blob_data_found = blob_storage_controller->GetBlobDataFromUrl(blob_url4); + EXPECT_FALSE(blob_data_found != NULL); + + // Test unregistering a blob URL. + blob_storage_controller->UnregisterBlobUrl(blob_url3); + blob_data_found = blob_storage_controller->GetBlobDataFromUrl(blob_url3); + EXPECT_FALSE(blob_data_found != NULL); +} + +} // namespace webkit_blob diff --git a/webkit/blob/webkit_blob.gypi b/webkit/blob/webkit_blob.gypi new file mode 100644 index 0000000..fcfddfb --- /dev/null +++ b/webkit/blob/webkit_blob.gypi @@ -0,0 +1,31 @@ +# Copyright (c) 2010 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. + +{ + 'targets': [ + { + 'target_name': 'blob', + 'type': '<(library)', + 'msvs_guid': '02567509-F7CA-4E84-8524-4F72DA2D3111', + 'dependencies': [ + '<(DEPTH)/app/app.gyp:app_base', + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/net/net.gyp:net', + ], + 'sources': [ + 'blob_data.cc', + 'blob_data.h', + 'blob_storage_controller.cc', + 'blob_storage_controller.h', + ], + 'conditions': [ + ['inside_chromium_build==0', { + 'dependencies': [ + '<(DEPTH)/webkit/support/setup_third_party.gyp:third_party_headers', + ], + }], + ], + }, + ], +} |