summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/DEPS3
-rw-r--r--chrome/browser/chrome_blob_storage_context.cc22
-rw-r--r--chrome/browser/chrome_blob_storage_context.h46
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc3
-rw-r--r--chrome/browser/net/chrome_url_request_context.h11
-rw-r--r--chrome/browser/profile.cc15
-rw-r--r--chrome/browser/profile.h5
-rw-r--r--chrome/browser/profile_impl.cc12
-rw-r--r--chrome/browser/profile_impl.h3
-rw-r--r--chrome/browser/renderer_host/blob_dispatcher_host.cc67
-rw-r--r--chrome/browser/renderer_host/blob_dispatcher_host.h47
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc11
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h4
-rw-r--r--chrome/chrome_browser.gypi5
-rw-r--r--chrome/chrome_common.gypi3
-rw-r--r--chrome/common/common_param_traits.cc114
-rw-r--r--chrome/common/common_param_traits.h13
-rw-r--r--chrome/common/render_messages.cc1
-rw-r--r--chrome/common/render_messages_internal.h21
-rw-r--r--chrome/common/webblobregistry_impl.cc41
-rw-r--r--chrome/common/webblobregistry_impl.h35
-rw-r--r--chrome/renderer/renderer_webkitclient_impl.cc11
-rw-r--r--chrome/renderer/renderer_webkitclient_impl.h4
-rw-r--r--chrome/test/testing_profile.h4
-rw-r--r--chrome/worker/worker_thread.cc1
-rw-r--r--chrome/worker/worker_webkitclient_impl.cc9
-rw-r--r--chrome/worker/worker_webkitclient_impl.h5
-rw-r--r--net/base/upload_data.cc3
-rw-r--r--net/base/upload_data.h18
-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
-rw-r--r--webkit/glue/glue_serialize.cc13
-rw-r--r--webkit/support/webkit_support.gyp1
-rw-r--r--webkit/tools/test_shell/test_shell.gypi2
38 files changed, 1078 insertions, 9 deletions
diff --git a/chrome/DEPS b/chrome/DEPS
index 9bae8b9..e38a2f8 100644
--- a/chrome/DEPS
+++ b/chrome/DEPS
@@ -23,6 +23,9 @@ include_rules = [
# Allow inclusion of the appcache library.
"+webkit/appcache",
+ # Allow inclusion of the blob library.
+ "+webkit/blob",
+
# Allow inclusion of the database library.
"+webkit/database",
diff --git a/chrome/browser/chrome_blob_storage_context.cc b/chrome/browser/chrome_blob_storage_context.cc
new file mode 100644
index 0000000..c59ce0b
--- /dev/null
+++ b/chrome/browser/chrome_blob_storage_context.cc
@@ -0,0 +1,22 @@
+// 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 "chrome/browser/chrome_blob_storage_context.h"
+
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "webkit/blob/blob_storage_controller.h"
+
+using webkit_blob::BlobStorageController;
+
+ChromeBlobStorageContext::ChromeBlobStorageContext() {
+}
+
+void ChromeBlobStorageContext::InitializeOnIOThread() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ controller_.reset(new BlobStorageController());
+}
+
+ChromeBlobStorageContext::~ChromeBlobStorageContext() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+}
diff --git a/chrome/browser/chrome_blob_storage_context.h b/chrome/browser/chrome_blob_storage_context.h
new file mode 100644
index 0000000..f4e39a6
--- /dev/null
+++ b/chrome/browser/chrome_blob_storage_context.h
@@ -0,0 +1,46 @@
+// 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 CHROME_BROWSER_CHROME_BLOB_STORAGE_CONTEXT_H_
+#define CHROME_BROWSER_CHROME_BLOB_STORAGE_CONTEXT_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/chrome_thread.h"
+
+class GURL;
+
+namespace webkit_blob {
+class BlobStorageController;
+}
+
+// A context class that keeps track of BlobStorageController used by the chrome.
+// There is an instance associated with each Profile. There could be multiple
+// URLRequestContexts in the same profile that refers to the same instance.
+//
+// All methods, except the ctor, are expected to be called on
+// the IO thread (unless specifically called out in doc comments).
+class ChromeBlobStorageContext
+ : public base::RefCountedThreadSafe<ChromeBlobStorageContext,
+ ChromeThread::DeleteOnIOThread> {
+ public:
+ ChromeBlobStorageContext();
+
+ void InitializeOnIOThread();
+
+ webkit_blob::BlobStorageController* controller() const {
+ return controller_.get();
+ }
+
+ private:
+ friend class ChromeThread;
+ friend class DeleteTask<ChromeBlobStorageContext>;
+
+ virtual ~ChromeBlobStorageContext();
+
+ scoped_ptr<webkit_blob::BlobStorageController> controller_;
+};
+
+#endif // CHROME_BROWSER_CHROME_BLOB_STORAGE_CONTEXT_H_
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index f5a21f8..c4104a5 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -907,6 +907,7 @@ ChromeURLRequestContext::ChromeURLRequestContext(
host_zoom_map_ = other->host_zoom_map_;
is_media_ = other->is_media_;
is_off_the_record_ = other->is_off_the_record_;
+ blob_storage_context_ = other->blob_storage_context_;
}
void ChromeURLRequestContext::OnAcceptLanguageChange(
@@ -989,6 +990,7 @@ ChromeURLRequestContextFactory::ChromeURLRequestContextFactory(Profile* profile)
cookie_monster_delegate_ = new ChromeCookieMonsterDelegate(profile);
appcache_service_ = profile->GetAppCacheService();
database_tracker_ = profile->GetDatabaseTracker();
+ blob_storage_context_ = profile->GetBlobStorageContext();
}
ChromeURLRequestContextFactory::~ChromeURLRequestContextFactory() {
@@ -1013,6 +1015,7 @@ void ChromeURLRequestContextFactory::ApplyProfileParametersToContext(
context->set_ssl_config_service(ssl_config_service_);
context->set_appcache_service(appcache_service_);
context->set_database_tracker(database_tracker_);
+ context->set_blob_storage_context(blob_storage_context_);
}
// ----------------------------------------------------------------------------
diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h
index 493c3e0..2638d46 100644
--- a/chrome/browser/net/chrome_url_request_context.h
+++ b/chrome/browser/net/chrome_url_request_context.h
@@ -13,6 +13,7 @@
#include "base/file_path.h"
#include "base/linked_ptr.h"
#include "chrome/browser/appcache/chrome_appcache_service.h"
+#include "chrome/browser/chrome_blob_storage_context.h"
#include "chrome/browser/host_content_settings_map.h"
#include "chrome/browser/host_zoom_map.h"
#include "chrome/browser/io_thread.h"
@@ -111,6 +112,11 @@ class ChromeURLRequestContext : public URLRequestContext {
return database_tracker_.get();
}
+ // Gets the blob storage context associated with this context's profile.
+ ChromeBlobStorageContext* blob_storage_context() const {
+ return blob_storage_context_.get();
+ }
+
bool is_off_the_record() const {
return is_off_the_record_;
}
@@ -213,6 +219,9 @@ class ChromeURLRequestContext : public URLRequestContext {
void set_database_tracker(webkit_database::DatabaseTracker* tracker) {
database_tracker_ = tracker;
}
+ void set_blob_storage_context(ChromeBlobStorageContext* context) {
+ blob_storage_context_ = context;
+ }
void set_net_log(net::NetLog* net_log) {
net_log_ = net_log;
}
@@ -238,6 +247,7 @@ class ChromeURLRequestContext : public URLRequestContext {
scoped_refptr<ChromeCookiePolicy> chrome_cookie_policy_;
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
scoped_refptr<HostZoomMap> host_zoom_map_;
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
bool is_media_;
bool is_off_the_record_;
@@ -400,6 +410,7 @@ class ChromeURLRequestContextFactory {
scoped_refptr<net::TransportSecurityState> transport_security_state_;
scoped_refptr<net::SSLConfigService> ssl_config_service_;
scoped_refptr<net::CookieMonster::Delegate> cookie_monster_delegate_;
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
FilePath profile_dir_path_;
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 15a4641..7b9e0fd 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/background_contents_service.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_blob_storage_context.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/find_bar_state.h"
@@ -515,6 +516,18 @@ class OffTheRecordProfileImpl : public Profile,
ExitedOffTheRecordMode();
}
+ virtual ChromeBlobStorageContext* GetBlobStorageContext() {
+ if (!blob_storage_context_) {
+ blob_storage_context_ = new ChromeBlobStorageContext();
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ blob_storage_context_.get(),
+ &ChromeBlobStorageContext::InitializeOnIOThread));
+ }
+ return blob_storage_context_;
+ }
+
private:
NotificationRegistrar registrar_;
@@ -566,6 +579,8 @@ class OffTheRecordProfileImpl : public Profile,
// Tracks all BackgroundContents running under this profile.
scoped_ptr<BackgroundContentsService> background_contents_service_;
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+
DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImpl);
};
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 9d3034c..4dc3f5b 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -40,6 +40,7 @@ class BackgroundModeManager;
class BookmarkModel;
class BrowserThemeProvider;
class ChromeAppCacheService;
+class ChromeBlobStorageContext;
class ChromeURLRequestContextGetter;
class DesktopNotificationService;
class DownloadManager;
@@ -429,6 +430,10 @@ class Profile {
virtual FilePath last_selected_directory() = 0;
virtual void set_last_selected_directory(const FilePath& path) = 0;
+ // Returns a pointer to the ChromeBlobStorageContext instance for this
+ // profile.
+ virtual ChromeBlobStorageContext* GetBlobStorageContext() = 0;
+
#if defined(OS_CHROMEOS)
// Returns ChromeOS's ProxyConfigServiceImpl, creating if not yet created.
virtual chromeos::ProxyConfigServiceImpl*
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index 677cf69..650b956 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_blob_storage_context.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_ui/ntp_resource_cache.h"
#include "chrome/browser/download/download_manager.h"
@@ -1220,6 +1221,17 @@ void ProfileImpl::InitCloudPrintProxyService() {
cloud_print_proxy_service_->Initialize();
}
+ChromeBlobStorageContext* ProfileImpl::GetBlobStorageContext() {
+ if (!blob_storage_context_) {
+ blob_storage_context_ = new ChromeBlobStorageContext();
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(blob_storage_context_.get(),
+ &ChromeBlobStorageContext::InitializeOnIOThread));
+ }
+ return blob_storage_context_;
+}
+
#if defined(OS_CHROMEOS)
chromeos::ProxyConfigServiceImpl*
ProfileImpl::GetChromeOSProxyConfigServiceImpl() {
diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h
index a948e4c5..83815e6 100644
--- a/chrome/browser/profile_impl.h
+++ b/chrome/browser/profile_impl.h
@@ -103,6 +103,7 @@ class ProfileImpl : public Profile,
void InitSyncService();
virtual CloudPrintProxyService* GetCloudPrintProxyService();
void InitCloudPrintProxyService();
+ virtual ChromeBlobStorageContext* GetBlobStorageContext();
#if defined(OS_CHROMEOS)
virtual chromeos::ProxyConfigServiceImpl* GetChromeOSProxyConfigServiceImpl();
@@ -233,6 +234,8 @@ class ProfileImpl : public Profile,
scoped_refptr<history::TopSites> top_sites_; // For history and thumbnails.
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+
#if defined(OS_CHROMEOS)
chromeos::Preferences chromeos_preferences_;
diff --git a/chrome/browser/renderer_host/blob_dispatcher_host.cc b/chrome/browser/renderer_host/blob_dispatcher_host.cc
new file mode 100644
index 0000000..f7eff24
--- /dev/null
+++ b/chrome/browser/renderer_host/blob_dispatcher_host.cc
@@ -0,0 +1,67 @@
+// 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 "chrome/browser/renderer_host/blob_dispatcher_host.h"
+
+#include "chrome/browser/chrome_blob_storage_context.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/render_messages.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message.h"
+#include "webkit/blob/blob_data.h"
+#include "webkit/blob/blob_storage_controller.h"
+
+BlobDispatcherHost::BlobDispatcherHost(
+ ChromeBlobStorageContext* blob_storage_context)
+ : blob_storage_context_(blob_storage_context) {
+}
+
+BlobDispatcherHost::~BlobDispatcherHost() {
+}
+
+void BlobDispatcherHost::Shutdown() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ // Unregister all the blob URLs that are previously registered in this
+ // process.
+ for (base::hash_set<std::string>::const_iterator iter = blob_urls_.begin();
+ iter != blob_urls_.end(); ++iter) {
+ blob_storage_context_->controller()->UnregisterBlobUrl(GURL(*iter));
+ }
+}
+
+bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message,
+ bool* msg_is_ok) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ *msg_is_ok = true;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(BlobDispatcherHost, message, *msg_is_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterBlobUrl, OnRegisterBlobUrl)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterBlobUrlFrom, OnRegisterBlobUrlFrom)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UnregisterBlobUrl, OnUnregisterBlobUrl)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void BlobDispatcherHost::OnRegisterBlobUrl(
+ const GURL& url, const scoped_refptr<webkit_blob::BlobData>& blob_data) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ blob_storage_context_->controller()->RegisterBlobUrl(url, blob_data);
+ blob_urls_.insert(url.spec());
+}
+
+void BlobDispatcherHost::OnRegisterBlobUrlFrom(
+ const GURL& url, const GURL& src_url) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ blob_storage_context_->controller()->RegisterBlobUrlFrom(url, src_url);
+ blob_urls_.insert(src_url.spec());
+}
+
+void BlobDispatcherHost::OnUnregisterBlobUrl(const GURL& url) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ blob_storage_context_->controller()->UnregisterBlobUrl(url);
+ blob_urls_.erase(url.spec());
+}
diff --git a/chrome/browser/renderer_host/blob_dispatcher_host.h b/chrome/browser/renderer_host/blob_dispatcher_host.h
new file mode 100644
index 0000000..9f0a0f8
--- /dev/null
+++ b/chrome/browser/renderer_host/blob_dispatcher_host.h
@@ -0,0 +1,47 @@
+// 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 CHROME_BROWSER_RENDERER_HOST_BLOB_DISPATCHER_HOST_H_
+#define CHROME_BROWSER_RENDERER_HOST_BLOB_DISPATCHER_HOST_H_
+
+#include "base/hash_tables.h"
+#include "base/ref_counted.h"
+
+class ChromeBlobStorageContext;
+class GURL;
+
+namespace IPC {
+class Message;
+}
+
+namespace webkit_blob {
+class BlobData;
+}
+
+class BlobDispatcherHost {
+ public:
+ explicit BlobDispatcherHost(
+ ChromeBlobStorageContext* blob_storage_context);
+ ~BlobDispatcherHost();
+
+ void Shutdown();
+ bool OnMessageReceived(const IPC::Message& message, bool* msg_is_ok);
+
+ private:
+
+ void OnRegisterBlobUrl(const GURL& url,
+ const scoped_refptr<webkit_blob::BlobData>& blob_data);
+ void OnRegisterBlobUrlFrom(const GURL& url, const GURL& src_url);
+ void OnUnregisterBlobUrl(const GURL& url);
+
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+
+ // Keep track of blob URLs registered in this process. Need to unregister
+ // all of them when the renderer process dies.
+ base::hash_set<std::string> blob_urls_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(BlobDispatcherHost);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_BLOB_DISPATCHER_HOST_H_
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index e9e3591..db9e6e4 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -49,6 +49,7 @@
#include "chrome/browser/printing/printer_query.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/audio_renderer_host.h"
+#include "chrome/browser/renderer_host/blob_dispatcher_host.h"
#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/browser/renderer_host/database_dispatcher_host.h"
#include "chrome/browser/renderer_host/render_view_host_notification_task.h"
@@ -255,7 +256,9 @@ ResourceMessageFilter::ResourceMessageFilter(
new device_orientation::DispatcherHost(this->id()))),
ALLOW_THIS_IN_INITIALIZER_LIST(file_system_dispatcher_host_(
new FileSystemDispatcherHost(this,
- profile->GetHostContentSettingsMap()))) {
+ profile->GetHostContentSettingsMap()))),
+ ALLOW_THIS_IN_INITIALIZER_LIST(blob_dispatcher_host_(
+ new BlobDispatcherHost(profile->GetBlobStorageContext()))) {
request_context_ = profile_->GetRequestContext();
DCHECK(request_context_);
DCHECK(media_request_context_);
@@ -288,6 +291,9 @@ ResourceMessageFilter::~ResourceMessageFilter() {
// Shut down the async file_system dispatcher host.
file_system_dispatcher_host_->Shutdown();
+ // Shut down the blob dispatcher host.
+ blob_dispatcher_host_->Shutdown();
+
// Let interested observers know we are being deleted.
NotificationService::current()->Notify(
NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN,
@@ -363,7 +369,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
search_provider_install_state_dispatcher_host_->OnMessageReceived(
msg, &msg_is_ok) ||
device_orientation_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) ||
- file_system_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok);
+ file_system_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) ||
+ blob_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok);
if (!handled) {
DCHECK(msg_is_ok); // It should have been marked handled if it wasn't OK.
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 5f55e04..dc839bb 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -32,6 +32,7 @@
class AppCacheDispatcherHost;
class AudioRendererHost;
+class BlobDispatcherHost;
class ChromeURLRequestContext;
class DatabaseDispatcherHost;
class DOMStorageDispatcherHost;
@@ -483,6 +484,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// Handles FileSystem API related messages
scoped_refptr<FileSystemDispatcherHost> file_system_dispatcher_host_;
+ // Handles blob related messages.
+ scoped_ptr<BlobDispatcherHost> blob_dispatcher_host_;
+
DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter);
};
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index a907800..338f9d9 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -37,6 +37,7 @@
'../third_party/hunspell/hunspell.gyp:hunspell',
'../third_party/speex/speex.gyp:libspeex',
'../webkit/support/webkit_support.gyp:appcache',
+ '../webkit/support/webkit_support.gyp:blob',
'../webkit/support/webkit_support.gyp:database',
'../webkit/support/webkit_support.gyp:glue',
'../webkit/support/webkit_support.gyp:webkit_resources',
@@ -347,6 +348,8 @@
'browser/child_process_launcher.h',
'browser/child_process_security_policy.cc',
'browser/child_process_security_policy.h',
+ 'browser/chrome_blob_storage_context.cc',
+ 'browser/chrome_blob_storage_context.h',
'browser/chrome_browser_application_mac.h',
'browser/chrome_browser_application_mac.mm',
'browser/chrome_plugin_browsing_context.cc',
@@ -2277,6 +2280,8 @@
'browser/renderer_host/backing_store_win.h',
'browser/renderer_host/backing_store_x.cc',
'browser/renderer_host/backing_store_x.h',
+ 'browser/renderer_host/blob_dispatcher_host.cc',
+ 'browser/renderer_host/blob_dispatcher_host.h',
'browser/renderer_host/browser_render_process_host.cc',
'browser/renderer_host/browser_render_process_host.h',
'browser/renderer_host/buffered_resource_handler.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index c4eb678..991278a 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -116,6 +116,8 @@
'common/time_format.h',
'common/chrome_version_info.h',
'common/chrome_version_info.cc',
+ 'common/webblobregistry_impl.cc',
+ 'common/webblobregistry_impl.h',
'common/win_safe_util.cc',
'common/win_safe_util.h',
],
@@ -164,6 +166,7 @@
'../third_party/zlib/zlib.gyp:zlib',
'../third_party/npapi/npapi.gyp:npapi',
'../webkit/support/webkit_support.gyp:appcache',
+ '../webkit/support/webkit_support.gyp:blob',
'../webkit/support/webkit_support.gyp:glue',
],
'sources': [
diff --git a/chrome/common/common_param_traits.cc b/chrome/common/common_param_traits.cc
index 19ef93b..f3c44c1 100644
--- a/chrome/common/common_param_traits.cc
+++ b/chrome/common/common_param_traits.cc
@@ -17,6 +17,7 @@
#ifndef EXCLUDE_SKIA_DEPENDENCIES
#include "third_party/skia/include/core/SkBitmap.h"
#endif
+#include "webkit/blob/blob_data.h"
#include "webkit/glue/dom_operations.h"
#include "webkit/glue/password_form.h"
@@ -327,11 +328,13 @@ struct ParamTraits<net::UploadData::Element> {
WriteParam(m, static_cast<int>(p.type()));
if (p.type() == net::UploadData::TYPE_BYTES) {
m->WriteData(&p.bytes()[0], static_cast<int>(p.bytes().size()));
- } else {
+ } else if (p.type() == net::UploadData::TYPE_FILE) {
WriteParam(m, p.file_path());
WriteParam(m, p.file_range_offset());
WriteParam(m, p.file_range_length());
WriteParam(m, p.expected_file_modification_time());
+ } else {
+ WriteParam(m, p.blob_url());
}
}
static bool Read(const Message* m, void** iter, param_type* r) {
@@ -344,8 +347,7 @@ struct ParamTraits<net::UploadData::Element> {
if (!m->ReadData(iter, &data, &len))
return false;
r->SetToBytes(data, len);
- } else {
- DCHECK(type == net::UploadData::TYPE_FILE);
+ } else if (type == net::UploadData::TYPE_FILE) {
FilePath file_path;
uint64 offset, length;
base::Time expected_modification_time;
@@ -359,6 +361,12 @@ struct ParamTraits<net::UploadData::Element> {
return false;
r->SetToFilePathRange(file_path, offset, length,
expected_modification_time);
+ } else {
+ DCHECK(type == net::UploadData::TYPE_BLOB);
+ GURL blob_url;
+ if (!ReadParam(m, iter, &blob_url))
+ return false;
+ r->SetToBlobUrl(blob_url);
}
return true;
}
@@ -401,6 +409,106 @@ void ParamTraits<scoped_refptr<net::UploadData> >::Log(const param_type& p,
l->append("<net::UploadData>");
}
+// Only the webkit_blob::BlobData ParamTraits<> definition needs this
+// definition, so keep this in the implementation file so we can forward declare
+// BlobData in the header.
+template <>
+struct ParamTraits<webkit_blob::BlobData::Item> {
+ typedef webkit_blob::BlobData::Item param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p.type()));
+ if (p.type() == webkit_blob::BlobData::TYPE_DATA) {
+ WriteParam(m, p.data());
+ } else if (p.type() == webkit_blob::BlobData::TYPE_FILE) {
+ WriteParam(m, p.file_path());
+ WriteParam(m, p.offset());
+ WriteParam(m, p.length());
+ WriteParam(m, p.expected_modification_time());
+ } else {
+ WriteParam(m, p.blob_url());
+ WriteParam(m, p.offset());
+ WriteParam(m, p.length());
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int type;
+ if (!ReadParam(m, iter, &type))
+ return false;
+ if (type == webkit_blob::BlobData::TYPE_DATA) {
+ std::string data;
+ if (!ReadParam(m, iter, &data))
+ return false;
+ r->SetToData(data);
+ } else if (type == webkit_blob::BlobData::TYPE_FILE) {
+ FilePath file_path;
+ uint64 offset, length;
+ base::Time expected_modification_time;
+ if (!ReadParam(m, iter, &file_path))
+ return false;
+ if (!ReadParam(m, iter, &offset))
+ return false;
+ if (!ReadParam(m, iter, &length))
+ return false;
+ if (!ReadParam(m, iter, &expected_modification_time))
+ return false;
+ r->SetToFile(file_path, offset, length, expected_modification_time);
+ } else {
+ DCHECK(type == webkit_blob::BlobData::TYPE_BLOB);
+ GURL blob_url;
+ uint64 offset, length;
+ if (!ReadParam(m, iter, &blob_url))
+ return false;
+ if (!ReadParam(m, iter, &offset))
+ return false;
+ if (!ReadParam(m, iter, &length))
+ return false;
+ r->SetToBlob(blob_url, offset, length);
+ }
+ return true;
+ }
+ static void Log(const param_type& p, std::string* l) {
+ l->append("<BlobData::Item>");
+ }
+};
+
+void ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Write(
+ Message* m, const param_type& p) {
+ WriteParam(m, p.get() != NULL);
+ if (p) {
+ WriteParam(m, p->items());
+ WriteParam(m, p->content_type());
+ WriteParam(m, p->content_disposition());
+ }
+}
+
+bool ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Read(
+ const Message* m, void** iter, param_type* r) {
+ bool has_object;
+ if (!ReadParam(m, iter, &has_object))
+ return false;
+ if (!has_object)
+ return true;
+ std::vector<webkit_blob::BlobData::Item> items;
+ if (!ReadParam(m, iter, &items))
+ return false;
+ std::string content_type;
+ if (!ReadParam(m, iter, &content_type))
+ return false;
+ std::string content_disposition;
+ if (!ReadParam(m, iter, &content_disposition))
+ return false;
+ *r = new webkit_blob::BlobData;
+ (*r)->swap_items(&items);
+ (*r)->set_content_type(content_type);
+ (*r)->set_content_disposition(content_disposition);
+ return true;
+}
+
+void ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Log(
+ const param_type& p, std::string* l) {
+ l->append("<webkit_blob::BlobData>");
+}
+
void ParamTraits<ThumbnailScore>::Write(Message* m, const param_type& p) {
IPC::ParamTraits<double>::Write(m, p.boring_score);
IPC::ParamTraits<bool>::Write(m, p.good_clipping);
diff --git a/chrome/common/common_param_traits.h b/chrome/common/common_param_traits.h
index da04edc..d77f15c 100644
--- a/chrome/common/common_param_traits.h
+++ b/chrome/common/common_param_traits.h
@@ -49,6 +49,10 @@ namespace printing {
struct PageRange;
} // namespace printing
+namespace webkit_blob {
+class BlobData;
+}
+
namespace webkit_glue {
struct PasswordForm;
struct WebApplicationInfo;
@@ -272,6 +276,15 @@ struct ParamTraits<scoped_refptr<net::UploadData> > {
static void Log(const param_type& p, std::string* l);
};
+// Traits for webkit_blob::BlobData.
+template <>
+struct ParamTraits<scoped_refptr<webkit_blob::BlobData> > {
+ typedef scoped_refptr<webkit_blob::BlobData> param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
template<>
struct ParamTraits<ThumbnailScore> {
typedef ThumbnailScore param_type;
diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc
index 3e17733..1bc1116 100644
--- a/chrome/common/render_messages.cc
+++ b/chrome/common/render_messages.cc
@@ -21,6 +21,7 @@
#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerAction.h"
#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
#include "webkit/appcache/appcache_interfaces.h"
+#include "webkit/blob/blob_data.h"
#include "webkit/glue/context_menu.h"
#include "webkit/glue/form_data.h"
#include "webkit/glue/form_field.h"
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 64d5f6c..3b0a13f 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -51,6 +51,10 @@ struct ChannelHandle;
class Message;
}
+namespace webkit_blob {
+class BlobData;
+}
+
//-----------------------------------------------------------------------------
// RenderView messages
// These are messages sent from the browser to the renderer process.
@@ -2710,4 +2714,21 @@ IPC_BEGIN_MESSAGES(ViewHost)
string16 /* src path */,
string16 /* dest path */)
+ //---------------------------------------------------------------------------
+ // Blob messages:
+
+ // Registers a blob URL referring to the specified blob data.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_RegisterBlobUrl,
+ GURL /* url */,
+ scoped_refptr<webkit_blob::BlobData> /* blob_data */)
+
+ // Registers a blob URL referring to the blob data identified by the specified
+ // source URL.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_RegisterBlobUrlFrom,
+ GURL /* url */,
+ GURL /* src_url */)
+
+ // Unregister a blob URL.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_UnregisterBlobUrl, GURL /* url */)
+
IPC_END_MESSAGES(ViewHost)
diff --git a/chrome/common/webblobregistry_impl.cc b/chrome/common/webblobregistry_impl.cc
new file mode 100644
index 0000000..90bfcbf
--- /dev/null
+++ b/chrome/common/webblobregistry_impl.cc
@@ -0,0 +1,41 @@
+// 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 "chrome/common/webblobregistry_impl.h"
+
+#include "base/ref_counted.h"
+#include "chrome/common/render_messages.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBlobData.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBlobStorageData.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "webkit/blob/blob_data.h"
+
+using WebKit::WebBlobData;
+using WebKit::WebBlobStorageData;
+using WebKit::WebString;
+using WebKit::WebURL;
+
+WebBlobRegistryImpl::WebBlobRegistryImpl(IPC::Message::Sender* sender)
+ : sender_(sender) {
+}
+
+WebBlobRegistryImpl::~WebBlobRegistryImpl() {
+}
+
+void WebBlobRegistryImpl::registerBlobURL(
+ const WebURL& url, WebBlobData& data) {
+ scoped_refptr<webkit_blob::BlobData> blob_data(
+ new webkit_blob::BlobData(data));
+ sender_->Send(new ViewHostMsg_RegisterBlobUrl(url, blob_data));
+}
+
+void WebBlobRegistryImpl::registerBlobURL(
+ const WebURL& url, const WebURL& src_url) {
+ sender_->Send(new ViewHostMsg_RegisterBlobUrlFrom(url, src_url));
+}
+
+void WebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) {
+ sender_->Send(new ViewHostMsg_UnregisterBlobUrl(url));
+}
diff --git a/chrome/common/webblobregistry_impl.h b/chrome/common/webblobregistry_impl.h
new file mode 100644
index 0000000..79bd06c
--- /dev/null
+++ b/chrome/common/webblobregistry_impl.h
@@ -0,0 +1,35 @@
+// 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 CHROME_COMMON_WEBBLOBREGISTRY_IMPL_H_
+#define CHROME_COMMON_WEBBLOBREGISTRY_IMPL_H_
+#pragma once
+
+#include "ipc/ipc_message.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBlobRegistry.h"
+
+namespace WebKit {
+class WebBlobData;
+class WebBlobStorageData;
+class WebString;
+class WebURL;
+}
+
+class WebBlobRegistryImpl : public WebKit::WebBlobRegistry {
+ public:
+ explicit WebBlobRegistryImpl(IPC::Message::Sender* sender);
+ virtual ~WebBlobRegistryImpl();
+
+ // See WebBlobRegistry.h for documentation on these functions.
+ virtual void registerBlobURL(const WebKit::WebURL& url,
+ WebKit::WebBlobData& data);
+ virtual void registerBlobURL(const WebKit::WebURL& url,
+ const WebKit::WebURL& src_url);
+ virtual void unregisterBlobURL(const WebKit::WebURL& url);
+
+ private:
+ IPC::Message::Sender* sender_;
+};
+
+#endif // CHROME_COMMON_WEBBLOBREGISTRY_IMPL_H_
diff --git a/chrome/renderer/renderer_webkitclient_impl.cc b/chrome/renderer/renderer_webkitclient_impl.cc
index 0eaef37..ec5c08c 100644
--- a/chrome/renderer/renderer_webkitclient_impl.cc
+++ b/chrome/renderer/renderer_webkitclient_impl.cc
@@ -13,6 +13,7 @@
#include "chrome/common/database_util.h"
#include "chrome/common/file_system/webfilesystem_impl.h"
#include "chrome/common/render_messages.h"
+#include "chrome/common/webblobregistry_impl.h"
#include "chrome/common/webmessageportchannel_impl.h"
#include "chrome/plugin/npobject_util.h"
#include "chrome/renderer/net/renderer_net_predictor.h"
@@ -26,6 +27,7 @@
#include "chrome/renderer/websharedworkerrepository_impl.h"
#include "googleurl/src/gurl.h"
#include "ipc/ipc_sync_message_filter.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBlobRegistry.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebGraphicsContext3D.h"
#include "third_party/WebKit/WebKit/chromium/public/WebIDBFactory.h"
@@ -60,6 +62,7 @@
#include "base/file_descriptor_posix.h"
#endif
+using WebKit::WebBlobRegistry;
using WebKit::WebFileSystem;
using WebKit::WebFrame;
using WebKit::WebIDBFactory;
@@ -506,3 +509,11 @@ WebKit::WebString RendererWebKitClientImpl::signedPublicKeyAndChallengeString(
&signed_public_key));
return WebString::fromUTF8(signed_public_key);
}
+
+//------------------------------------------------------------------------------
+
+WebBlobRegistry* RendererWebKitClientImpl::blobRegistry() {
+ if (!blob_registry_.get())
+ blob_registry_.reset(new WebBlobRegistryImpl(RenderThread::current()));
+ return blob_registry_.get();
+}
diff --git a/chrome/renderer/renderer_webkitclient_impl.h b/chrome/renderer/renderer_webkitclient_impl.h
index cc1149c..d057391 100644
--- a/chrome/renderer/renderer_webkitclient_impl.h
+++ b/chrome/renderer/renderer_webkitclient_impl.h
@@ -68,6 +68,8 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl {
virtual WebKit::WebGraphicsContext3D* createGraphicsContext3D();
virtual WebKit::WebGLES2Context* createGLES2Context();
+ virtual WebKit::WebBlobRegistry* blobRegistry();
+
private:
bool CheckPreparsedJsCachingEnabled() const;
@@ -98,6 +100,8 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl {
scoped_ptr<WebKit::WebIDBFactory> web_idb_factory_;
scoped_ptr<WebFileSystemImpl> web_file_system_;
+
+ scoped_ptr<WebKit::WebBlobRegistry> blob_registry_;
};
#endif // CHROME_RENDERER_RENDERER_WEBKITCLIENT_IMPL_H_
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 539ae46..a080bd5 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -253,6 +253,10 @@ class TestingProfile : public Profile {
virtual ProfileSyncService* GetProfileSyncService();
virtual CloudPrintProxyService* GetCloudPrintProxyService() { return NULL; }
+ virtual ChromeBlobStorageContext* GetBlobStorageContext() {
+ return NULL;
+ }
+
protected:
base::Time start_time_;
scoped_ptr<TestingPrefService> prefs_;
diff --git a/chrome/worker/worker_thread.cc b/chrome/worker/worker_thread.cc
index b2e9f18..c493701 100644
--- a/chrome/worker/worker_thread.cc
+++ b/chrome/worker/worker_thread.cc
@@ -16,6 +16,7 @@
#include "chrome/worker/websharedworker_stub.h"
#include "chrome/worker/worker_webkitclient_impl.h"
#include "ipc/ipc_sync_channel.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBlobRegistry.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDatabase.h"
#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
#include "third_party/WebKit/WebKit/chromium/public/WebRuntimeFeatures.h"
diff --git a/chrome/worker/worker_webkitclient_impl.cc b/chrome/worker/worker_webkitclient_impl.cc
index 43a8e2f..b09ca7b 100644
--- a/chrome/worker/worker_webkitclient_impl.cc
+++ b/chrome/worker/worker_webkitclient_impl.cc
@@ -8,11 +8,14 @@
#include "chrome/common/database_util.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/render_messages_params.h"
+#include "chrome/common/webblobregistry_impl.h"
#include "chrome/common/webmessageportchannel_impl.h"
#include "chrome/worker/worker_thread.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBlobRegistry.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+using WebKit::WebBlobRegistry;
using WebKit::WebClipboard;
using WebKit::WebKitClient;
using WebKit::WebMessagePortChannel;
@@ -172,3 +175,9 @@ WebString WorkerWebKitClientImpl::preferredExtensionForMIMEType(
NOTREACHED();
return WebString();
}
+
+WebBlobRegistry* WorkerWebKitClientImpl::blobRegistry() {
+ if (!blob_registry_.get())
+ blob_registry_.reset(new WebBlobRegistryImpl(WorkerThread::current()));
+ return blob_registry_.get();
+}
diff --git a/chrome/worker/worker_webkitclient_impl.h b/chrome/worker/worker_webkitclient_impl.h
index 8a2bd46..6488c56 100644
--- a/chrome/worker/worker_webkitclient_impl.h
+++ b/chrome/worker/worker_webkitclient_impl.h
@@ -6,6 +6,7 @@
#define CHROME_WORKER_WORKER_WEBKITCLIENT_IMPL_H_
#pragma once
+#include "base/scoped_ptr.h"
#include "third_party/WebKit/WebKit/chromium/public/WebMimeRegistry.h"
#include "webkit/glue/webfileutilities_impl.h"
#include "webkit/glue/webkitclient_impl.h"
@@ -49,6 +50,8 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl,
virtual long long databaseGetFileSize(
const WebKit::WebString& vfs_file_name);
+ virtual WebKit::WebBlobRegistry* blobRegistry();
+
// WebMimeRegistry methods:
virtual WebKit::WebMimeRegistry::SupportsType supportsMIMEType(
const WebKit::WebString&);
@@ -67,6 +70,8 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl,
private:
webkit_glue::WebFileUtilitiesImpl file_utilities_;
+
+ scoped_ptr<WebKit::WebBlobRegistry> blob_registry_;
};
#endif // CHROME_WORKER_WORKER_WEBKITCLIENT_IMPL_H_
diff --git a/net/base/upload_data.cc b/net/base/upload_data.cc
index 198b051..f852d27 100644
--- a/net/base/upload_data.cc
+++ b/net/base/upload_data.cc
@@ -24,6 +24,9 @@ uint64 UploadData::Element::GetContentLength() {
if (type_ == TYPE_BYTES)
return static_cast<uint64>(bytes_.size());
+ else if (type_ == TYPE_BLOB)
+ // The blob reference will be resolved later.
+ return 0;
DCHECK_EQ(TYPE_FILE, type_);
DCHECK(!file_stream_);
diff --git a/net/base/upload_data.h b/net/base/upload_data.h
index 01ca0da..ffb668a 100644
--- a/net/base/upload_data.h
+++ b/net/base/upload_data.h
@@ -13,6 +13,7 @@
#include "base/gtest_prod_util.h"
#include "base/logging.h"
#include "base/ref_counted.h"
+#include "googleurl/src/gurl.h"
#include "net/base/file_stream.h"
#include "base/time.h"
@@ -24,7 +25,8 @@ class UploadData : public base::RefCounted<UploadData> {
enum Type {
TYPE_BYTES,
- TYPE_FILE
+ TYPE_FILE,
+ TYPE_BLOB
};
class Element {
@@ -50,6 +52,7 @@ class UploadData : public base::RefCounted<UploadData> {
const base::Time& expected_file_modification_time() const {
return expected_file_modification_time_;
}
+ const GURL& blob_url() const { return blob_url_; }
void SetToBytes(const char* bytes, int bytes_len) {
type_ = TYPE_BYTES;
@@ -73,6 +76,13 @@ class UploadData : public base::RefCounted<UploadData> {
expected_file_modification_time_ = expected_modification_time;
}
+ // TODO(jianli): UploadData should not contain any blob reference. We need
+ // to define another structure to represent WebKit::WebHTTPBody.
+ void SetToBlobUrl(const GURL& blob_url) {
+ type_ = TYPE_BLOB;
+ blob_url_ = blob_url;
+ }
+
// Returns the byte-length of the element. For files that do not exist, 0
// is returned. This is done for consistency with Mozilla.
// Once called, this function will always return the same value.
@@ -97,6 +107,7 @@ class UploadData : public base::RefCounted<UploadData> {
uint64 file_range_offset_;
uint64 file_range_length_;
base::Time expected_file_modification_time_;
+ GURL blob_url_;
bool override_content_length_;
bool content_length_computed_;
uint64 content_length_;
@@ -127,6 +138,11 @@ class UploadData : public base::RefCounted<UploadData> {
expected_modification_time);
}
+ void AppendBlob(const GURL& blob_url) {
+ elements_.push_back(Element());
+ elements_.back().SetToBlobUrl(blob_url);
+ }
+
// Returns the total size in bytes of the data to upload.
uint64 GetContentLength();
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',
+ ],
+ }],
+ ],
+ },
+ ],
+}
diff --git a/webkit/glue/glue_serialize.cc b/webkit/glue/glue_serialize.cc
index d0b9a86..8190c2f 100644
--- a/webkit/glue/glue_serialize.cc
+++ b/webkit/glue/glue_serialize.cc
@@ -15,6 +15,7 @@
#include "third_party/WebKit/WebKit/chromium/public/WebPoint.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
#include "webkit/glue/webkit_glue.h"
@@ -56,12 +57,13 @@ struct SerializeObject {
// 7: Adds support for stateObject
// 8: Adds support for file range and modification time
// 9: Adds support for itemSequenceNumbers
+// 10: Adds support for blob
// Should be const, but unit tests may modify it.
//
// NOTE: If the version is -1, then the pickle contains only a URL string.
// See CreateHistoryStateForURL.
//
-int kVersion = 9;
+int kVersion = 10;
// A bunch of convenience functions to read/write to SerializeObjects.
// The serializers assume the input data is in the correct format and so does
@@ -234,11 +236,13 @@ static void WriteFormData(const WebHTTPBody& http_body, SerializeObject* obj) {
if (element.type == WebHTTPBody::Element::TypeData) {
WriteData(element.data.data(), static_cast<int>(element.data.size()),
obj);
- } else {
+ } else if (element.type == WebHTTPBody::Element::TypeFile) {
WriteString(element.filePath, obj);
WriteInteger64(element.fileStart, obj);
WriteInteger64(element.fileLength, obj);
WriteReal(element.fileInfo.modificationTime, obj);
+ } else {
+ WriteGURL(element.blobURL, obj);
}
}
WriteInteger64(http_body.identifier(), obj);
@@ -265,7 +269,7 @@ static WebHTTPBody ReadFormData(const SerializeObject* obj) {
ReadData(obj, &data, &length);
if (length >= 0)
http_body.appendData(WebData(static_cast<const char*>(data), length));
- } else {
+ } else if (type == WebHTTPBody::Element::TypeFile) {
WebString file_path = ReadString(obj);
long long file_start = 0;
long long file_length = -1;
@@ -276,6 +280,9 @@ static WebHTTPBody ReadFormData(const SerializeObject* obj) {
file_info.modificationTime = ReadReal(obj);
}
http_body.appendFileRange(file_path, file_start, file_length, file_info);
+ } else if (obj->version >= 10) {
+ GURL blob_url = ReadGURL(obj);
+ http_body.appendBlob(blob_url);
}
}
if (obj->version >= 4)
diff --git a/webkit/support/webkit_support.gyp b/webkit/support/webkit_support.gyp
index fb6052b..0de6dcb 100644
--- a/webkit/support/webkit_support.gyp
+++ b/webkit/support/webkit_support.gyp
@@ -5,6 +5,7 @@
{
'includes': [
'../appcache/webkit_appcache.gypi',
+ '../blob/webkit_blob.gypi',
'../database/webkit_database.gypi',
'../glue/webkit_glue.gypi',
# TODO(tkent): Merge npapi_layout_test_plugin into TestNetscapePlugIn
diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi
index 0a73531..08c5cfc 100644
--- a/webkit/tools/test_shell/test_shell.gypi
+++ b/webkit/tools/test_shell/test_shell.gypi
@@ -40,6 +40,7 @@
'<(DEPTH)/third_party/WebKit/WebKit/chromium/WebKit.gyp:inspector_resources',
'<(DEPTH)/third_party/WebKit/WebKit/chromium/WebKit.gyp:webkit',
'<(DEPTH)/webkit/support/webkit_support.gyp:appcache',
+ '<(DEPTH)/webkit/support/webkit_support.gyp:blob',
'<(DEPTH)/webkit/support/webkit_support.gyp:database',
'<(DEPTH)/webkit/support/webkit_support.gyp:glue',
'<(DEPTH)/webkit/support/webkit_support.gyp:webkit_resources',
@@ -367,6 +368,7 @@
'../../appcache/appcache_url_request_job_unittest.cc',
'../../appcache/mock_appcache_service.h',
'../../appcache/mock_appcache_storage_unittest.cc',
+ '../../blob/blob_storage_controller_unittest.cc',
'../../database/databases_table_unittest.cc',
'../../database/database_tracker_unittest.cc',
'../../database/database_util_unittest.cc',