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 | |
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
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', |