summaryrefslogtreecommitdiffstats
path: root/webkit/blob
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-27 18:29:24 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-27 18:29:24 +0000
commit22339b123c68805c7c293c67f6f47ea45f0fd1a1 (patch)
treebb05e2e3eb0362338e921a4dce9d5c350437326e /webkit/blob
parente840afdedd33728491639312a268fbf37a48f078 (diff)
downloadchromium_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.cc62
-rw-r--r--webkit/blob/blob_data.h196
-rw-r--r--webkit/blob/blob_storage_controller.cc117
-rw-r--r--webkit/blob/blob_storage_controller.h43
-rw-r--r--webkit/blob/blob_storage_controller_unittest.cc85
-rw-r--r--webkit/blob/webkit_blob.gypi31
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',
+ ],
+ }],
+ ],
+ },
+ ],
+}