diff options
60 files changed, 818 insertions, 949 deletions
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc index 3a2d71d8..20bf12c 100644 --- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc +++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/file_util.h" +#include "base/guid.h" #include "base/message_loop/message_loop_proxy.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" @@ -147,11 +148,13 @@ class WriteHelper { public: WriteHelper() : bytes_written_(0) {} WriteHelper(MockBlobURLRequestContext* request_context, - const GURL& blob_url, const std::string& blob_data) : bytes_written_(0), request_context_(request_context), - blob_data_(new ScopedTextBlob(*request_context, blob_url, blob_data)) {} + blob_data_(new ScopedTextBlob(*request_context, + base::GenerateGUID(), + blob_data)) { + } ~WriteHelper() { if (request_context_) { @@ -160,6 +163,8 @@ class WriteHelper { } } + ScopedTextBlob* scoped_text_blob() const { return blob_data_.get(); } + void DidWrite(const base::Callback<void(int64 result)>& completion_callback, PlatformFileError error, int64 bytes, bool complete) { if (error == base::PLATFORM_FILE_OK) { @@ -448,14 +453,15 @@ PlatformFileError CannedSyncableFileSystem::ReadDirectory( int64 CannedSyncableFileSystem::Write( net::URLRequestContext* url_request_context, - const FileSystemURL& url, const GURL& blob_url) { + const FileSystemURL& url, + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle) { return RunOnThread<int64>(io_task_runner_.get(), FROM_HERE, base::Bind(&CannedSyncableFileSystem::DoWrite, base::Unretained(this), url_request_context, url, - blob_url)); + base::Passed(&blob_data_handle))); } int64 CannedSyncableFileSystem::WriteString( @@ -626,11 +632,13 @@ void CannedSyncableFileSystem::DoReadDirectory( void CannedSyncableFileSystem::DoWrite( net::URLRequestContext* url_request_context, - const FileSystemURL& url, const GURL& blob_url, + const FileSystemURL& url, + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle, const WriteCallback& callback) { EXPECT_TRUE(is_filesystem_opened_); WriteHelper* helper = new WriteHelper; - operation_runner()->Write(url_request_context, url, blob_url, 0, + operation_runner()->Write(url_request_context, url, + blob_data_handle.Pass(), 0, base::Bind(&WriteHelper::DidWrite, base::Owned(helper), callback)); } @@ -641,9 +649,9 @@ void CannedSyncableFileSystem::DoWriteString( const WriteCallback& callback) { MockBlobURLRequestContext* url_request_context( new MockBlobURLRequestContext(file_system_context_.get())); - const GURL blob_url(std::string("blob:") + data); - WriteHelper* helper = new WriteHelper(url_request_context, blob_url, data); - operation_runner()->Write(url_request_context, url, blob_url, 0, + WriteHelper* helper = new WriteHelper(url_request_context, data); + operation_runner()->Write(url_request_context, url, + helper->scoped_text_blob()->GetBlobDataHandle(), 0, base::Bind(&WriteHelper::DidWrite, base::Owned(helper), callback)); } diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.h b/chrome/browser/sync_file_system/local/canned_syncable_file_system.h index ff20b23..440e779 100644 --- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.h +++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.h @@ -15,6 +15,7 @@ #include "base/platform_file.h" #include "chrome/browser/sync_file_system/local/local_file_sync_status.h" #include "chrome/browser/sync_file_system/sync_status_code.h" +#include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/quota/quota_callbacks.h" @@ -126,7 +127,8 @@ class CannedSyncableFileSystem // Returns the # of bytes written (>=0) or an error code (<0). int64 Write(net::URLRequestContext* url_request_context, - const fileapi::FileSystemURL& url, const GURL& blob_url); + const fileapi::FileSystemURL& url, + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle); int64 WriteString(const fileapi::FileSystemURL& url, const std::string& data); // Purges the file system local storage. @@ -184,7 +186,7 @@ class CannedSyncableFileSystem const StatusCallback& callback); void DoWrite(net::URLRequestContext* url_request_context, const fileapi::FileSystemURL& url, - const GURL& blob_url, + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle, const WriteCallback& callback); void DoWriteString(const fileapi::FileSystemURL& url, const std::string& data, diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc index 23cd37d..de0128d 100644 --- a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc +++ b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc @@ -205,10 +205,9 @@ TEST_F(LocalFileChangeTrackerTest, RestoreCreateAndModifyChanges) { file_system_.GetChangedURLsInTracker(&urls); ASSERT_EQ(0U, urls.size()); - const GURL blob_url("blob:test"); const std::string kData("Lorem ipsum."); MockBlobURLRequestContext url_request_context(file_system_context()); - ScopedTextBlob blob(url_request_context, blob_url, kData); + ScopedTextBlob blob(url_request_context, "blob_id:test", kData); // Create files and nested directories. EXPECT_EQ(base::PLATFORM_FILE_OK, @@ -223,9 +222,9 @@ TEST_F(LocalFileChangeTrackerTest, RestoreCreateAndModifyChanges) { file_system_.TruncateFile(URL(kPath3), 1)); // Modifies the file. EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateFile(URL(kPath4))); // Creates another file. - EXPECT_EQ(static_cast<int64>(kData.size()), + EXPECT_EQ(static_cast<int64>(kData.size()), // Modifies the file. file_system_.Write(&url_request_context, - URL(kPath4), blob_url)); // Modifies the file. + URL(kPath4), blob.GetBlobDataHandle())); // Verify the changes. file_system_.GetChangedURLsInTracker(&urls); @@ -357,10 +356,9 @@ TEST_F(LocalFileChangeTrackerTest, RestoreCopyChanges) { file_system_.GetChangedURLsInTracker(&urls); ASSERT_EQ(0U, urls.size()); - const GURL blob_url("blob:test"); const std::string kData("Lorem ipsum."); MockBlobURLRequestContext url_request_context(file_system_context()); - ScopedTextBlob blob(url_request_context, blob_url, kData); + ScopedTextBlob blob(url_request_context, "blob_id:test", kData); // Create files and nested directories. EXPECT_EQ(base::PLATFORM_FILE_OK, @@ -376,8 +374,8 @@ TEST_F(LocalFileChangeTrackerTest, RestoreCopyChanges) { EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateFile(URL(kPath4))); // Creates another file. EXPECT_EQ(static_cast<int64>(kData.size()), - file_system_.Write(&url_request_context, - URL(kPath4), blob_url)); // Modifies the file. + file_system_.Write(&url_request_context, // Modifies the file. + URL(kPath4), blob.GetBlobDataHandle())); // Verify we have 5 changes for preparation. file_system_.GetChangedURLsInTracker(&urls); diff --git a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc index 524c82f..a76c1bd 100644 --- a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc +++ b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc @@ -287,16 +287,15 @@ TEST_F(SyncableFileOperationRunnerTest, CopyAndMove) { TEST_F(SyncableFileOperationRunnerTest, Write) { EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.CreateFile(URL(kFile))); - const GURL kBlobURL("blob:foo"); const std::string kData("Lorem ipsum."); - ScopedTextBlob blob(url_request_context_, kBlobURL, kData); + ScopedTextBlob blob(url_request_context_, "blob:foo", kData); sync_status()->StartSyncing(URL(kFile)); ResetCallbackStatus(); file_system_.operation_runner()->Write( &url_request_context_, - URL(kFile), kBlobURL, 0, GetWriteCallback(FROM_HERE)); + URL(kFile), blob.GetBlobDataHandle(), 0, GetWriteCallback(FROM_HERE)); base::MessageLoop::current()->RunUntilIdle(); EXPECT_EQ(0, callback_count_); diff --git a/content/browser/fileapi/chrome_blob_storage_context.cc b/content/browser/fileapi/chrome_blob_storage_context.cc index 728b0d5..97151a8 100644 --- a/content/browser/fileapi/chrome_blob_storage_context.cc +++ b/content/browser/fileapi/chrome_blob_storage_context.cc @@ -7,10 +7,10 @@ #include "base/bind.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" using base::UserDataAdapter; -using webkit_blob::BlobStorageController; +using webkit_blob::BlobStorageContext; namespace content { @@ -40,7 +40,7 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor( void ChromeBlobStorageContext::InitializeOnIOThread() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - controller_.reset(new BlobStorageController()); + context_.reset(new BlobStorageContext()); } ChromeBlobStorageContext::~ChromeBlobStorageContext() {} diff --git a/content/browser/fileapi/chrome_blob_storage_context.h b/content/browser/fileapi/chrome_blob_storage_context.h index 3992e0e..641e235 100644 --- a/content/browser/fileapi/chrome_blob_storage_context.h +++ b/content/browser/fileapi/chrome_blob_storage_context.h @@ -11,7 +11,7 @@ #include "content/common/content_export.h" namespace webkit_blob { -class BlobStorageController; +class BlobStorageContext; } namespace content { @@ -36,8 +36,8 @@ class CONTENT_EXPORT ChromeBlobStorageContext void InitializeOnIOThread(); - webkit_blob::BlobStorageController* controller() const { - return controller_.get(); + webkit_blob::BlobStorageContext* context() const { + return context_.get(); } protected: @@ -51,7 +51,7 @@ class CONTENT_EXPORT ChromeBlobStorageContext void DeleteOnCorrectThread() const; - scoped_ptr<webkit_blob::BlobStorageController> controller_; + scoped_ptr<webkit_blob::BlobStorageContext> context_; }; struct ChromeBlobStorageContextDeleter { diff --git a/content/browser/fileapi/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc index b4b5aef..8025f40 100644 --- a/content/browser/fileapi/fileapi_message_filter.cc +++ b/content/browser/fileapi/fileapi_message_filter.cc @@ -28,7 +28,8 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "url/gurl.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" +#include "webkit/browser/blob/blob_storage_host.h" #include "webkit/browser/fileapi/file_observers.h" #include "webkit/browser/fileapi/file_permission_policy.h" #include "webkit/browser/fileapi/file_system_context.h" @@ -47,7 +48,8 @@ using fileapi::FileSystemURL; using fileapi::FileUpdateObserver; using fileapi::UpdateObserverList; using webkit_blob::BlobData; -using webkit_blob::BlobStorageController; +using webkit_blob::BlobStorageContext; +using webkit_blob::BlobStorageHost; namespace content { @@ -106,6 +108,9 @@ void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) { DCHECK(request_context_); } + blob_storage_host_.reset( + new BlobStorageHost(blob_storage_context_->context())); + operation_runner_ = context_->CreateFileSystemOperationRunner(); } @@ -115,10 +120,7 @@ void FileAPIMessageFilter::OnChannelClosing() { // Unregister all the blob and stream 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()->RemoveBlob(GURL(*iter)); - } + blob_storage_host_.reset(); for (base::hash_set<std::string>::const_iterator iter = stream_urls_.begin(); iter != stream_urls_.end(); ++iter) { stream_context_->registry()->UnregisterStream(GURL(*iter)); @@ -168,6 +170,7 @@ bool FileAPIMessageFilter::OnMessageReceived( IPC_MESSAGE_HANDLER(FileSystemHostMsg_Exists, OnExists) IPC_MESSAGE_HANDLER(FileSystemHostMsg_ReadDirectory, OnReadDirectory) IPC_MESSAGE_HANDLER(FileSystemHostMsg_Write, OnWrite) + IPC_MESSAGE_HANDLER(FileSystemHostMsg_WriteDeprecated, OnWriteDeprecated) IPC_MESSAGE_HANDLER(FileSystemHostMsg_Truncate, OnTruncate) IPC_MESSAGE_HANDLER(FileSystemHostMsg_TouchFile, OnTouchFile) IPC_MESSAGE_HANDLER(FileSystemHostMsg_CancelWrite, OnCancel) @@ -187,8 +190,19 @@ bool FileAPIMessageFilter::OnMessageReceived( IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemory, OnAppendSharedMemoryToBlob) IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuilding, OnFinishBuildingBlob) - IPC_MESSAGE_HANDLER(BlobHostMsg_Clone, OnCloneBlob) - IPC_MESSAGE_HANDLER(BlobHostMsg_Remove, OnRemoveBlob) + IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, + OnIncrementBlobRefCount) + IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, + OnDecrementBlobRefCount) + IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, + OnRegisterPublicBlobURL) + IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL) + IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedRegisterBlobURL, + OnDeprecatedRegisterBlobURL) + IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedRevokeBlobURL, + OnDeprecatedRevokeBlobURL) + IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedCloneBlobURL, + OnDeprecatedCloneBlobURL) IPC_MESSAGE_HANDLER(StreamHostMsg_StartBuilding, OnStartBuildingStream) IPC_MESSAGE_HANDLER(StreamHostMsg_AppendBlobDataItem, OnAppendBlobDataItemToStream) @@ -361,11 +375,21 @@ void FileAPIMessageFilter::OnReadDirectory( this, request_id)); } -void FileAPIMessageFilter::OnWrite( +void FileAPIMessageFilter::OnWriteDeprecated( int request_id, const GURL& path, const GURL& blob_url, int64 offset) { + std::string uuid = + blob_storage_context_->context()->LookupUuidFromDeprecatedURL(blob_url); + OnWrite(request_id, path, uuid, offset); +} + +void FileAPIMessageFilter::OnWrite( + int request_id, + const GURL& path, + const std::string& blob_uuid, + int64 offset) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (!request_context_) { // We can't write w/o a request context, trying to do so will crash. @@ -380,8 +404,11 @@ void FileAPIMessageFilter::OnWrite( return; } + scoped_ptr<webkit_blob::BlobDataHandle> blob = + blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid); + operations_[request_id] = operation_runner()->Write( - request_context_, url, blob_url, offset, + request_context_, url, blob.Pass(), offset, base::Bind(&FileAPIMessageFilter::DidWrite, this, request_id)); } @@ -537,39 +564,40 @@ void FileAPIMessageFilter::OnDidReceiveSnapshotFile(int request_id) { in_transit_snapshot_files_.erase(request_id); } -void FileAPIMessageFilter::OnStartBuildingBlob(const GURL& url) { +void FileAPIMessageFilter::OnStartBuildingBlob(const std::string& uuid) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - blob_storage_context_->controller()->StartBuildingBlob(url); - blob_urls_.insert(url.spec()); + ignore_result(blob_storage_host_->StartBuildingBlob(uuid)); } void FileAPIMessageFilter::OnAppendBlobDataItemToBlob( - const GURL& url, const BlobData::Item& item) { + const std::string& uuid, const BlobData::Item& item) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (item.type() == BlobData::Item::TYPE_FILE_FILESYSTEM) { base::PlatformFileError error; - FileSystemURL filesystem_url(context_->CrackURL(item.url())); + FileSystemURL filesystem_url(context_->CrackURL(item.filesystem_url())); if (!HasPermissionsForFile(filesystem_url, fileapi::kReadFilePermissions, &error)) { - OnRemoveBlob(url); + ignore_result(blob_storage_host_->CancelBuildingBlob(uuid)); return; } } if (item.type() == BlobData::Item::TYPE_FILE && !ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( process_id_, item.path())) { - OnRemoveBlob(url); + ignore_result(blob_storage_host_->CancelBuildingBlob(uuid)); return; } if (item.length() == 0) { BadMessageReceived(); return; } - blob_storage_context_->controller()->AppendBlobDataItem(url, item); + ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item)); } void FileAPIMessageFilter::OnAppendSharedMemoryToBlob( - const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size) { + const std::string& uuid, + base::SharedMemoryHandle handle, + size_t buffer_size) { DCHECK(base::SharedMemory::IsHandleValid(handle)); if (!buffer_size) { BadMessageReceived(); @@ -581,33 +609,59 @@ void FileAPIMessageFilter::OnAppendSharedMemoryToBlob( base::SharedMemory shared_memory(handle, true); #endif if (!shared_memory.Map(buffer_size)) { - OnRemoveBlob(url); + ignore_result(blob_storage_host_->CancelBuildingBlob(uuid)); return; } BlobData::Item item; item.SetToSharedBytes(static_cast<char*>(shared_memory.memory()), buffer_size); - blob_storage_context_->controller()->AppendBlobDataItem(url, item); + ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item)); } void FileAPIMessageFilter::OnFinishBuildingBlob( - const GURL& url, const std::string& content_type) { + const std::string& uuid, const std::string& content_type) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ignore_result(blob_storage_host_->FinishBuildingBlob(uuid, content_type)); + // TODO(michaeln): check return values once blink has migrated, crbug/174200 +} + +void FileAPIMessageFilter::OnIncrementBlobRefCount(const std::string& uuid) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ignore_result(blob_storage_host_->IncrementBlobRefCount(uuid)); +} + +void FileAPIMessageFilter::OnDecrementBlobRefCount(const std::string& uuid) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ignore_result(blob_storage_host_->DecrementBlobRefCount(uuid)); +} + +void FileAPIMessageFilter::OnRegisterPublicBlobURL( + const GURL& public_url, const std::string& uuid) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ignore_result(blob_storage_host_->RegisterPublicBlobURL(public_url, uuid)); +} + +void FileAPIMessageFilter::OnRevokePublicBlobURL(const GURL& public_url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ignore_result(blob_storage_host_->RevokePublicBlobURL(public_url)); +} + +void FileAPIMessageFilter::OnDeprecatedRegisterBlobURL( + const GURL& url, const std::string& uuid) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - blob_storage_context_->controller()->FinishBuildingBlob(url, content_type); + blob_storage_host_->DeprecatedRegisterBlobURL(url, uuid); } -void FileAPIMessageFilter::OnCloneBlob( +void FileAPIMessageFilter::OnDeprecatedCloneBlobURL( const GURL& url, const GURL& src_url) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - blob_storage_context_->controller()->CloneBlob(url, src_url); - blob_urls_.insert(url.spec()); + blob_storage_host_->DeprecatedCloneBlobURL(url, src_url); } -void FileAPIMessageFilter::OnRemoveBlob(const GURL& url) { +void FileAPIMessageFilter::OnDeprecatedRevokeBlobURL(const GURL& url) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - blob_storage_context_->controller()->RemoveBlob(url); - blob_urls_.erase(url.spec()); + blob_storage_host_->DeprecatedRevokeBlobURL(url); } void FileAPIMessageFilter::OnStartBuildingStream( diff --git a/content/browser/fileapi/fileapi_message_filter.h b/content/browser/fileapi/fileapi_message_filter.h index 873d010..6a3b231 100644 --- a/content/browser/fileapi/fileapi_message_filter.h +++ b/content/browser/fileapi/fileapi_message_filter.h @@ -45,6 +45,7 @@ class URLRequestContextGetter; } // namespace net namespace webkit_blob { +class BlobStorageHost; class ShareableFileReference; } @@ -111,6 +112,11 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter { void OnReadDirectory(int request_id, const GURL& path); void OnWrite(int request_id, const GURL& path, + const std::string& blob_uuid, + int64 offset); + void OnWriteDeprecated( + int request_id, + const GURL& path, const GURL& blob_url, int64 offset); void OnTruncate(int request_id, const GURL& path, int64 length); @@ -131,14 +137,26 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter { // Handlers for BlobHostMsg_ family messages. - void OnStartBuildingBlob(const GURL& url); - void OnAppendBlobDataItemToBlob( - const GURL& url, const webkit_blob::BlobData::Item& item); - void OnAppendSharedMemoryToBlob( - const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size); - void OnFinishBuildingBlob(const GURL& url, const std::string& content_type); - void OnCloneBlob(const GURL& url, const GURL& src_url); - void OnRemoveBlob(const GURL& url); + void OnStartBuildingBlob(const std::string& uuid); + void OnAppendBlobDataItemToBlob(const std::string& uuid, + const webkit_blob::BlobData::Item& item); + void OnAppendSharedMemoryToBlob(const std::string& uuid, + base::SharedMemoryHandle handle, + size_t buffer_size); + void OnFinishBuildingBlob(const std::string& uuid, + const std::string& content_type); + void OnCancelBuildingBlob(const std::string& uuid); + void OnIncrementBlobRefCount(const std::string& uuid); + void OnDecrementBlobRefCount(const std::string& uuid); + void OnRegisterPublicBlobURL(const GURL& public_url, const std::string& uuid); + void OnRevokePublicBlobURL(const GURL& public_url); + + // Extra methods to establish a mapping from old-style blobURLs to uuids, + // and to clone them. These won't be here for long, just during a + // transition period. See crbug/174200 + void OnDeprecatedRegisterBlobURL(const GURL& url, const std::string& uuid); + void OnDeprecatedCloneBlobURL(const GURL& url, const GURL& existing_url); + void OnDeprecatedRevokeBlobURL(const GURL& url); // Handlers for StreamHostMsg_ family messages. // @@ -225,9 +243,9 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter { scoped_ptr<fileapi::FileSystemOperationRunner> operation_runner_; - // 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_; + // Keeps track of blobs used in this process and cleans up + // when the renderer process dies. + scoped_ptr<webkit_blob::BlobStorageHost> blob_storage_host_; // Keep track of stream URLs registered in this process. Need to unregister // all of them when the renderer process dies. diff --git a/content/browser/fileapi/fileapi_message_filter_unittest.cc b/content/browser/fileapi/fileapi_message_filter_unittest.cc index 06b112b..90e422c 100644 --- a/content/browser/fileapi/fileapi_message_filter_unittest.cc +++ b/content/browser/fileapi/fileapi_message_filter_unittest.cc @@ -23,7 +23,7 @@ #include "content/public/test/test_browser_thread.h" #include "net/base/io_buffer.h" #include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/mock_file_system_context.h" #include "webkit/common/blob/blob_data.h" @@ -95,34 +95,6 @@ class FileAPIMessageFilterTest : public testing::Test { scoped_refptr<FileAPIMessageFilter> filter_; }; -TEST_F(FileAPIMessageFilterTest, BuildEmptyBlob) { - webkit_blob::BlobStorageController* controller = - blob_storage_context_->controller(); - - const GURL kUrl("blob:foobar"); - const GURL kDifferentUrl("blob:barfoo"); - - EXPECT_EQ(NULL, controller->GetBlobDataFromUrl(kUrl)); - - BlobHostMsg_StartBuilding start_message(kUrl); - EXPECT_TRUE(InvokeOnMessageReceived(start_message)); - - // Blob is still being built. Nothing should be returned. - EXPECT_EQ(NULL, controller->GetBlobDataFromUrl(kUrl)); - - BlobHostMsg_FinishBuilding finish_message(kUrl, kFakeContentType); - EXPECT_TRUE(InvokeOnMessageReceived(finish_message)); - - // Now, Blob is built. - webkit_blob::BlobData* blob_data = controller->GetBlobDataFromUrl(kUrl); - ASSERT_FALSE(blob_data == NULL); - EXPECT_EQ(0U, blob_data->items().size()); - EXPECT_EQ(kFakeContentType, blob_data->content_type()); - - // Nothing should be returned for a URL we didn't use. - EXPECT_TRUE(controller->GetBlobDataFromUrl(kDifferentUrl) == NULL); -} - TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) { scoped_refptr<FileAPIMessageFilter> filter( new FileAPIMessageFilter( @@ -190,14 +162,10 @@ TEST_F(FileAPIMessageFilterTest, MultipleFilters) { TEST_F(FileAPIMessageFilterTest, BuildEmptyStream) { StreamRegistry* stream_registry = stream_context_->registry(); - webkit_blob::BlobStorageController* blob_controller = - blob_storage_context_->controller(); - const GURL kUrl(kFakeBlobInternalUrlSpec); const GURL kDifferentUrl("blob:barfoo"); EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get()); - EXPECT_EQ(NULL, blob_controller->GetBlobDataFromUrl(kUrl)); StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType); EXPECT_TRUE(InvokeOnMessageReceived(start_message)); @@ -217,9 +185,6 @@ TEST_F(FileAPIMessageFilterTest, BuildEmptyStream) { StreamHostMsg_FinishBuilding finish_message(kUrl); EXPECT_TRUE(InvokeOnMessageReceived(finish_message)); - // Blob controller shouldn't be affected. - EXPECT_EQ(NULL, blob_controller->GetBlobDataFromUrl(kUrl)); - stream = stream_registry->GetStream(kUrl); ASSERT_FALSE(stream.get() == NULL); EXPECT_EQ(Stream::STREAM_EMPTY, diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 2a4ad9a..22912ed 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc @@ -87,7 +87,10 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory.h" #include "webkit/browser/appcache/appcache_interceptor.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/common/blob/blob_data.h" +#include "webkit/browser/blob/blob_data_handle.h" +#include "webkit/browser/blob/blob_storage_context.h" +#include "webkit/browser/blob/blob_url_request_job_factory.h" #include "webkit/browser/fileapi/file_permission_policy.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/common/appcache/appcache_interfaces.h" @@ -216,11 +219,12 @@ bool ShouldServiceRequest(int process_type, return false; } if (iter->type() == ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM) { - fileapi::FileSystemURL url = file_system_context->CrackURL(iter->url()); + fileapi::FileSystemURL url = + file_system_context->CrackURL(iter->filesystem_url()); if (!policy->HasPermissionsForFileSystemFile( child_id, url, fileapi::kReadFilePermissions)) { NOTREACHED() << "Denied unauthorized upload of " - << iter->url().spec(); + << iter->filesystem_url().spec(); return false; } } @@ -502,6 +506,14 @@ net::Error ResourceDispatcherHostImpl::BeginDownload( CreateRequestInfo(child_id, route_id, true, context); extra_info->AssociateWithRequest(request.get()); // Request takes ownership. + if (request->url().SchemeIs(chrome::kBlobScheme)) { + ChromeBlobStorageContext* blob_context = + GetChromeBlobStorageContextForResourceContext(context); + webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle( + request.get(), + blob_context->context()->GetBlobDataFromPublicURL(request->url())); + } + // From this point forward, the |DownloadResourceHandler| is responsible for // |started_callback|. scoped_ptr<ResourceHandler> handler( @@ -982,7 +994,7 @@ void ResourceDispatcherHostImpl::BeginRequest( if (request_data.request_body.get()) { request->set_upload(UploadDataStreamBuilder::Build( request_data.request_body.get(), - filter_->blob_storage_context()->controller(), + filter_->blob_storage_context()->context(), filter_->file_system_context(), BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) .get())); @@ -1017,9 +1029,10 @@ void ResourceDispatcherHostImpl::BeginRequest( if (request->url().SchemeIs(chrome::kBlobScheme)) { // Hang on to a reference to ensure the blob is not released prior // to the job being started. - extra_info->set_requested_blob_data( - filter_->blob_storage_context()->controller()-> - GetBlobDataFromUrl(request->url())); + webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle( + request, + filter_->blob_storage_context()->context()-> + GetBlobDataFromPublicURL(request->url())); } // Have the appcache associate its extra info with the request. diff --git a/content/browser/loader/resource_request_info_impl.cc b/content/browser/loader/resource_request_info_impl.cc index 51e39ff..e7b2828 100644 --- a/content/browser/loader/resource_request_info_impl.cc +++ b/content/browser/loader/resource_request_info_impl.cc @@ -9,7 +9,6 @@ #include "content/common/net/url_request_user_data.h" #include "content/public/browser/global_request_id.h" #include "net/url_request/url_request.h" -#include "webkit/common/blob/blob_data.h" namespace content { @@ -226,9 +225,4 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const { return GlobalRoutingID(child_id_, route_id_); } -void ResourceRequestInfoImpl::set_requested_blob_data( - webkit_blob::BlobData* data) { - requested_blob_data_ = data; -} - } // namespace content diff --git a/content/browser/loader/resource_request_info_impl.h b/content/browser/loader/resource_request_info_impl.h index d9958653..e615116 100644 --- a/content/browser/loader/resource_request_info_impl.h +++ b/content/browser/loader/resource_request_info_impl.h @@ -16,10 +16,6 @@ #include "net/base/load_states.h" #include "webkit/common/resource_type.h" -namespace webkit_blob { -class BlobData; -} - namespace content { class CrossSiteResourceHandler; class ResourceContext; @@ -116,13 +112,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, int memory_cost() const { return memory_cost_; } void set_memory_cost(int cost) { memory_cost_ = cost; } - // We hold a reference to the requested blob data to ensure it doesn't - // get finally released prior to the net::URLRequestJob being started. - webkit_blob::BlobData* requested_blob_data() const { - return requested_blob_data_.get(); - } - void set_requested_blob_data(webkit_blob::BlobData* data); - private: // Non-owning, may be NULL. CrossSiteResourceHandler* cross_site_handler_; @@ -144,7 +133,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, ResourceType::Type resource_type_; PageTransition transition_type_; int memory_cost_; - scoped_refptr<webkit_blob::BlobData> requested_blob_data_; WebKit::WebReferrerPolicy referrer_policy_; ResourceContext* context_; bool is_async_; diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc index 1a7dfc3..c22a8a8 100644 --- a/content/browser/loader/upload_data_stream_builder.cc +++ b/content/browser/loader/upload_data_stream_builder.cc @@ -8,12 +8,14 @@ #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_data_handle.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/fileapi/upload_file_system_file_element_reader.h" #include "webkit/common/resource_request_body.h" using webkit_blob::BlobData; -using webkit_blob::BlobStorageController; +using webkit_blob::BlobDataHandle; +using webkit_blob::BlobStorageContext; using webkit_glue::ResourceRequestBody; namespace content { @@ -64,49 +66,51 @@ class FileElementReader : public net::UploadFileElementReader { void ResolveBlobReference( ResourceRequestBody* body, - webkit_blob::BlobStorageController* blob_controller, - const GURL& blob_url, + webkit_blob::BlobStorageContext* blob_context, + const ResourceRequestBody::Element& element, std::vector<const ResourceRequestBody::Element*>* resolved_elements) { - DCHECK(blob_controller); - BlobData* blob_data = blob_controller->GetBlobDataFromUrl(blob_url); - DCHECK(blob_data); - if (!blob_data) + DCHECK(blob_context); + std::string uuid = element.blob_uuid(); + if (uuid.empty()) + uuid = blob_context->LookupUuidFromDeprecatedURL(element.blob_url()); + scoped_ptr<webkit_blob::BlobDataHandle> handle = + blob_context->GetBlobDataFromUUID(uuid); + DCHECK(handle); + if (!handle) return; // If there is no element in the referred blob data, just return. - if (blob_data->items().empty()) + if (handle->data()->items().empty()) return; - // Ensure the blob and any attached shareable files survive until - // upload completion. - body->SetUserData(blob_data, new base::UserDataAdapter<BlobData>(blob_data)); - - // Append the elements in the referred blob data. - for (size_t i = 0; i < blob_data->items().size(); ++i) { - const BlobData::Item& item = blob_data->items().at(i); + // Append the elements in the referenced blob data. + for (size_t i = 0; i < handle->data()->items().size(); ++i) { + const BlobData::Item& item = handle->data()->items().at(i); DCHECK_NE(BlobData::Item::TYPE_BLOB, item.type()); resolved_elements->push_back(&item); } + + // Ensure the blob and any attached shareable files survive until + // upload completion. The |body| takes ownership of |handle|. + const void* key = handle.get(); + body->SetUserData(key, handle.release()); } } // namespace scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build( ResourceRequestBody* body, - BlobStorageController* blob_controller, + BlobStorageContext* blob_context, fileapi::FileSystemContext* file_system_context, base::TaskRunner* file_task_runner) { // Resolve all blob elements. std::vector<const ResourceRequestBody::Element*> resolved_elements; for (size_t i = 0; i < body->elements()->size(); ++i) { const ResourceRequestBody::Element& element = (*body->elements())[i]; - if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) { - ResolveBlobReference(body, blob_controller, element.url(), - &resolved_elements); - } else { - // No need to resolve, just append the element. + if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) + ResolveBlobReference(body, blob_context, element, &resolved_elements); + else resolved_elements.push_back(&element); - } } ScopedVector<net::UploadElementReader> element_readers; @@ -124,7 +128,7 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build( element_readers.push_back( new fileapi::UploadFileSystemFileElementReader( file_system_context, - element.url(), + element.filesystem_url(), element.offset(), element.length(), element.expected_modification_time())); diff --git a/content/browser/loader/upload_data_stream_builder.h b/content/browser/loader/upload_data_stream_builder.h index b511546..e2b6ce3 100644 --- a/content/browser/loader/upload_data_stream_builder.h +++ b/content/browser/loader/upload_data_stream_builder.h @@ -21,7 +21,7 @@ class UploadDataStream; } namespace webkit_blob { -class BlobStorageController; +class BlobStorageContext; } namespace webkit_glue { @@ -34,7 +34,7 @@ class CONTENT_EXPORT UploadDataStreamBuilder { public: // Creates a new UploadDataStream from this request body. // - // This also resolves any blob references using the given |blob_controller| + // This also resolves any blob references using the given |blob_context| // and binds those blob references to the ResourceRequestBody ensuring that // the blob data remains valid for the lifetime of the ResourceRequestBody // object. @@ -44,7 +44,7 @@ class CONTENT_EXPORT UploadDataStreamBuilder { // when the data gets uploaded. static scoped_ptr<net::UploadDataStream> Build( webkit_glue::ResourceRequestBody* body, - webkit_blob::BlobStorageController* blob_controller, + webkit_blob::BlobStorageContext* blob_context, fileapi::FileSystemContext* file_system_context, base::TaskRunner* file_task_runner); }; diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc index 9972418..4c9661c 100644 --- a/content/browser/loader/upload_data_stream_builder_unittest.cc +++ b/content/browser/loader/upload_data_stream_builder_unittest.cc @@ -16,11 +16,12 @@ #include "net/base/upload_file_element_reader.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/common/resource_request_body.h" using webkit_blob::BlobData; -using webkit_blob::BlobStorageController; +using webkit_blob::BlobDataHandle; +using webkit_blob::BlobStorageContext; using webkit_glue::ResourceRequestBody; namespace content { @@ -98,24 +99,20 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2); - BlobStorageController blob_storage_controller; - scoped_refptr<BlobData> blob_data(new BlobData()); + BlobStorageContext blob_storage_context; - GURL blob_url0("blob://url_0"); - blob_storage_controller.AddFinishedBlob(blob_url0, blob_data.get()); + const std::string blob_id0("id-0"); + scoped_refptr<BlobData> blob_data(new BlobData(blob_id0)); + scoped_ptr<BlobDataHandle> handle1 = + blob_storage_context.AddFinishedBlob(blob_data); + const std::string blob_id1("id-1"); + blob_data = new BlobData(blob_id1); blob_data->AppendData("BlobData"); blob_data->AppendFile( base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); - - GURL blob_url1("blob://url_1"); - blob_storage_controller.AddFinishedBlob(blob_url1, blob_data.get()); - - GURL blob_url2("blob://url_2"); - blob_storage_controller.CloneBlob(blob_url2, blob_url1); - - GURL blob_url3("blob://url_3"); - blob_storage_controller.CloneBlob(blob_url3, blob_url2); + scoped_ptr<BlobDataHandle> handle2 = + blob_storage_context.AddFinishedBlob(blob_data); // Setup upload data elements for comparison. ResourceRequestBody::Element blob_element1, blob_element2; @@ -144,7 +141,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { scoped_ptr<net::UploadDataStream> upload( UploadDataStreamBuilder::Build(request_body.get(), - &blob_storage_controller, + &blob_storage_context, NULL, base::MessageLoopProxy::current().get())); @@ -154,22 +151,22 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { // Test having only one blob reference that refers to empty blob data. request_body = new ResourceRequestBody(); - request_body->AppendBlob(blob_url0); + request_body->AppendBlob(blob_id0); upload = UploadDataStreamBuilder::Build(request_body.get(), - &blob_storage_controller, + &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); ASSERT_EQ(0U, upload->element_readers().size()); // Test having only one blob reference. request_body = new ResourceRequestBody(); - request_body->AppendBlob(blob_url1); + request_body->AppendBlob(blob_id1); upload = UploadDataStreamBuilder::Build(request_body.get(), - &blob_storage_controller, + &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); ASSERT_EQ(2U, upload->element_readers().size()); @@ -178,7 +175,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { // Test having one blob reference at the beginning. request_body = new ResourceRequestBody(); - request_body->AppendBlob(blob_url1); + request_body->AppendBlob(blob_id1); request_body->AppendBytes(upload_element1.bytes(), upload_element1.length()); request_body->AppendFileRange(upload_element2.path(), upload_element2.offset(), @@ -187,7 +184,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { upload = UploadDataStreamBuilder::Build(request_body.get(), - &blob_storage_controller, + &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); ASSERT_EQ(4U, upload->element_readers().size()); @@ -203,11 +200,11 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { upload_element2.offset(), upload_element2.length(), upload_element2.expected_modification_time()); - request_body->AppendBlob(blob_url1); + request_body->AppendBlob(blob_id1); upload = UploadDataStreamBuilder::Build(request_body.get(), - &blob_storage_controller, + &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); ASSERT_EQ(4U, upload->element_readers().size()); @@ -219,7 +216,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { // Test having one blob reference in the middle. request_body = new ResourceRequestBody(); request_body->AppendBytes(upload_element1.bytes(), upload_element1.length()); - request_body->AppendBlob(blob_url1); + request_body->AppendBlob(blob_id1); request_body->AppendFileRange(upload_element2.path(), upload_element2.offset(), upload_element2.length(), @@ -227,7 +224,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { upload = UploadDataStreamBuilder::Build(request_body.get(), - &blob_storage_controller, + &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); ASSERT_EQ(4U, upload->element_readers().size()); @@ -238,10 +235,10 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { // Test having multiple blob references. request_body = new ResourceRequestBody(); - request_body->AppendBlob(blob_url1); + request_body->AppendBlob(blob_id1); request_body->AppendBytes(upload_element1.bytes(), upload_element1.length()); - request_body->AppendBlob(blob_url2); - request_body->AppendBlob(blob_url3); + request_body->AppendBlob(blob_id1); + request_body->AppendBlob(blob_id1); request_body->AppendFileRange(upload_element2.path(), upload_element2.offset(), upload_element2.length(), @@ -249,7 +246,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { upload = UploadDataStreamBuilder::Build(request_body.get(), - &blob_storage_controller, + &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); ASSERT_EQ(8U, upload->element_readers().size()); diff --git a/content/browser/net/view_blob_internals_job_factory.cc b/content/browser/net/view_blob_internals_job_factory.cc index e877a41..85356e5 100644 --- a/content/browser/net/view_blob_internals_job_factory.cc +++ b/content/browser/net/view_blob_internals_job_factory.cc @@ -21,9 +21,9 @@ bool ViewBlobInternalsJobFactory::IsSupportedURL(const GURL& url) { net::URLRequestJob* ViewBlobInternalsJobFactory::CreateJobForRequest( net::URLRequest* request, net::NetworkDelegate* network_delegate, - webkit_blob::BlobStorageController* blob_storage_controller) { + webkit_blob::BlobStorageContext* blob_storage_context) { return new webkit_blob::ViewBlobInternalsJob( - request, network_delegate, blob_storage_controller); + request, network_delegate, blob_storage_context); } } // namespace content diff --git a/content/browser/net/view_blob_internals_job_factory.h b/content/browser/net/view_blob_internals_job_factory.h index 0843e06..4d4b60a 100644 --- a/content/browser/net/view_blob_internals_job_factory.h +++ b/content/browser/net/view_blob_internals_job_factory.h @@ -11,7 +11,7 @@ class URLRequest; class URLRequestJob; } // namespace net namespace webkit_blob { -class BlobStorageController; +class BlobStorageContext; } // webkit_blob class GURL; @@ -24,7 +24,7 @@ class ViewBlobInternalsJobFactory { static net::URLRequestJob* CreateJobForRequest( net::URLRequest* request, net::NetworkDelegate* network_delegate, - webkit_blob::BlobStorageController* blob_storage_controller); + webkit_blob::BlobStorageContext* blob_storage_context); }; } // namespace content diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc index c5721ae..d02542c 100644 --- a/content/browser/storage_partition_impl_map.cc +++ b/content/browser/storage_partition_impl_map.cc @@ -34,96 +34,52 @@ #include "crypto/sha2.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/blob/blob_url_request_job_factory.h" #include "webkit/browser/fileapi/file_system_url_request_job_factory.h" #include "webkit/common/blob/blob_data.h" using appcache::AppCacheService; using fileapi::FileSystemContext; -using webkit_blob::BlobStorageController; +using webkit_blob::BlobStorageContext; namespace content { namespace { -class BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { +// A derivative that knows about Streams too. +class BlobProtocolHandler : public webkit_blob::BlobProtocolHandler { public: BlobProtocolHandler(ChromeBlobStorageContext* blob_storage_context, StreamContext* stream_context, fileapi::FileSystemContext* file_system_context) - : blob_storage_context_(blob_storage_context), + : webkit_blob::BlobProtocolHandler( + file_system_context, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) + .get()), + blob_storage_context_(blob_storage_context), stream_context_(stream_context), - file_system_context_(file_system_context) {} + file_system_context_(file_system_context) { + } - virtual ~BlobProtocolHandler() {} + virtual ~BlobProtocolHandler() { + } virtual net::URLRequestJob* MaybeCreateJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) const OVERRIDE { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (!webkit_blob_protocol_handler_impl_) { - webkit_blob_protocol_handler_impl_.reset( - new WebKitBlobProtocolHandlerImpl(blob_storage_context_->controller(), - stream_context_.get(), - file_system_context_.get())); - } - return webkit_blob_protocol_handler_impl_->MaybeCreateJob(request, - network_delegate); + scoped_refptr<Stream> stream = + stream_context_->registry()->GetStream(request->url()); + if (stream.get()) + return new StreamURLRequestJob(request, network_delegate, stream); + return webkit_blob::BlobProtocolHandler::MaybeCreateJob( + request, network_delegate); } private: - // An implementation of webkit_blob::BlobProtocolHandler that gets - // the BlobData from ResourceRequestInfoImpl. - class WebKitBlobProtocolHandlerImpl - : public webkit_blob::BlobProtocolHandler { - public: - WebKitBlobProtocolHandlerImpl( - webkit_blob::BlobStorageController* blob_storage_controller, - StreamContext* stream_context, - fileapi::FileSystemContext* file_system_context) - : webkit_blob::BlobProtocolHandler( - blob_storage_controller, - file_system_context, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) - .get()), - stream_context_(stream_context) {} - - virtual ~WebKitBlobProtocolHandlerImpl() {} - - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE { - scoped_refptr<Stream> stream = - stream_context_->registry()->GetStream(request->url()); - if (stream.get()) - return new StreamURLRequestJob(request, network_delegate, stream); - - return webkit_blob::BlobProtocolHandler::MaybeCreateJob( - request, network_delegate); - } - - private: - // webkit_blob::BlobProtocolHandler implementation. - virtual scoped_refptr<webkit_blob::BlobData> - LookupBlobData(net::URLRequest* request) const OVERRIDE { - const ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request); - if (!info) - return NULL; - return info->requested_blob_data(); - } - - const scoped_refptr<StreamContext> stream_context_; - DISALLOW_COPY_AND_ASSIGN(WebKitBlobProtocolHandlerImpl); - }; - const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; const scoped_refptr<StreamContext> stream_context_; const scoped_refptr<fileapi::FileSystemContext> file_system_context_; - - mutable scoped_ptr<WebKitBlobProtocolHandlerImpl> - webkit_blob_protocol_handler_impl_; - DISALLOW_COPY_AND_ASSIGN(BlobProtocolHandler); }; diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc index 7c4c77b..1bcbdb7 100644 --- a/content/browser/webui/url_data_manager_backend.cc +++ b/content/browser/webui/url_data_manager_backend.cc @@ -388,7 +388,7 @@ class ChromeProtocolHandler // Next check for chrome://blob-internals/, which uses its own job type. if (ViewBlobInternalsJobFactory::IsSupportedURL(request->url())) { return ViewBlobInternalsJobFactory::CreateJobForRequest( - request, network_delegate, blob_storage_context_->controller()); + request, network_delegate, blob_storage_context_->context()); } #if defined(USE_TCMALLOC) diff --git a/content/child/fileapi/file_system_dispatcher.cc b/content/child/fileapi/file_system_dispatcher.cc index b7a1367..095dc58 100644 --- a/content/child/fileapi/file_system_dispatcher.cc +++ b/content/child/fileapi/file_system_dispatcher.cc @@ -272,7 +272,7 @@ void FileSystemDispatcher::Truncate( *request_id_out = request_id; } -void FileSystemDispatcher::Write( +void FileSystemDispatcher::WriteDeprecated( const GURL& path, const GURL& blob_url, int64 offset, @@ -282,7 +282,24 @@ void FileSystemDispatcher::Write( int request_id = dispatchers_.Add( CallbackDispatcher::Create(success_callback, error_callback)); ChildThread::current()->Send( - new FileSystemHostMsg_Write(request_id, path, blob_url, offset)); + new FileSystemHostMsg_WriteDeprecated(request_id, path, + blob_url, offset)); + + if (request_id_out) + *request_id_out = request_id; +} + +void FileSystemDispatcher::Write( + const GURL& path, + const std::string& blob_id, + int64 offset, + int* request_id_out, + const WriteCallback& success_callback, + const StatusCallback& error_callback) { + int request_id = dispatchers_.Add( + CallbackDispatcher::Create(success_callback, error_callback)); + ChildThread::current()->Send( + new FileSystemHostMsg_Write(request_id, path, blob_id, offset)); if (request_id_out) *request_id_out = request_id; diff --git a/content/child/fileapi/file_system_dispatcher.h b/content/child/fileapi/file_system_dispatcher.h index e0260fda..7c34ba7 100644 --- a/content/child/fileapi/file_system_dispatcher.h +++ b/content/child/fileapi/file_system_dispatcher.h @@ -100,8 +100,15 @@ class FileSystemDispatcher : public IPC::Listener { int64 offset, int* request_id_out, const StatusCallback& callback); + void WriteDeprecated( + const GURL& path, + const GURL& blob_url, + int64 offset, + int* request_id_out, + const WriteCallback& success_callback, + const StatusCallback& error_callback); void Write(const GURL& path, - const GURL& blob_url, + const std::string& blob_id, int64 offset, int* request_id_out, const WriteCallback& success_callback, diff --git a/content/child/fileapi/webfilewriter_base.cc b/content/child/fileapi/webfilewriter_base.cc index fd0a207..cd8b756 100644 --- a/content/child/fileapi/webfilewriter_base.cc +++ b/content/child/fileapi/webfilewriter_base.cc @@ -32,10 +32,19 @@ void WebFileWriterBase::truncate(long long length) { void WebFileWriterBase::write(long long position, const WebKit::WebURL& blob_url) { - DCHECK(kOperationNone == operation_); - DCHECK(kCancelNotInProgress == cancel_state_); + DCHECK_EQ(kOperationNone, operation_); + DCHECK_EQ(kCancelNotInProgress, cancel_state_); + operation_ = kOperationWrite; + DoWriteDeprecated(path_, blob_url, position); +} + +void WebFileWriterBase::write( + long long position, + const WebKit::WebString& id) { + DCHECK_EQ(kOperationNone, operation_); + DCHECK_EQ(kCancelNotInProgress, cancel_state_); operation_ = kOperationWrite; - DoWrite(path_, blob_url, position); + DoWrite(path_, id.utf8(), position); } // When we cancel a write/truncate, we always get back the result of the write diff --git a/content/child/fileapi/webfilewriter_base.h b/content/child/fileapi/webfilewriter_base.h index d3873dc..c3abfe7 100644 --- a/content/child/fileapi/webfilewriter_base.h +++ b/content/child/fileapi/webfilewriter_base.h @@ -25,9 +25,12 @@ class CONTENT_EXPORT WebFileWriterBase // WebFileWriter implementation virtual void truncate(long long length); - virtual void write(long long position, const WebKit::WebURL& blobURL); + virtual void write(long long position, const WebKit::WebString& id); virtual void cancel(); + // DEPRECATED: see crbug/174200 + virtual void write(long long position, const WebKit::WebURL& blobURL); + protected: // This calls DidSucceed() or DidFail() based on the value of |error_code|. void DidFinish(base::PlatformFileError error_code); @@ -40,8 +43,11 @@ class CONTENT_EXPORT WebFileWriterBase // the requested operation, and they must call the appropiate DidSomething // method upon completion and as progress is made in the Write case. virtual void DoTruncate(const GURL& path, int64 offset) = 0; + virtual void DoWriteDeprecated(const GURL& path, + const GURL& blob_url, + int64 offset) = 0; virtual void DoWrite(const GURL& path, - const GURL& blob_url, + const std::string& blob_id, int64 offset) = 0; virtual void DoCancel() = 0; diff --git a/content/child/fileapi/webfilewriter_base_unittest.cc b/content/child/fileapi/webfilewriter_base_unittest.cc index 92150813..1895085 100644 --- a/content/child/fileapi/webfilewriter_base_unittest.cc +++ b/content/child/fileapi/webfilewriter_base_unittest.cc @@ -52,6 +52,7 @@ class TestableFileWriter : public WebFileWriterBase { received_write_path_ = GURL(); received_write_offset_ = kNoOffset; received_write_blob_url_ = GURL(); + received_write_blob_uuid_ = std::string(); received_cancel_ = false; } @@ -61,6 +62,7 @@ class TestableFileWriter : public WebFileWriterBase { bool received_write_; GURL received_write_path_; GURL received_write_blob_url_; + std::string received_write_blob_uuid_; int64 received_write_offset_; bool received_cancel_; @@ -87,8 +89,9 @@ class TestableFileWriter : public WebFileWriterBase { } } - virtual void DoWrite(const GURL& path, const GURL& blob_url, - int64 offset) OVERRIDE { + virtual void DoWriteDeprecated( + const GURL& path, const GURL& blob_url, + int64 offset) OVERRIDE { received_write_ = true; received_write_path_ = path; received_write_offset_ = offset; @@ -121,6 +124,41 @@ class TestableFileWriter : public WebFileWriterBase { } } + virtual void DoWrite( + const GURL& path, const std::string& blob_uuid, + int64 offset) OVERRIDE { + received_write_ = true; + received_write_path_ = path; + received_write_offset_ = offset; + received_write_blob_uuid_ = blob_uuid; + + if (offset == kBasicFileWrite_Offset) { + DidWrite(1, true); + } else if (offset == kErrorFileWrite_Offset) { + DidFail(base::PLATFORM_FILE_ERROR_NOT_FOUND); + } else if (offset == kMultiFileWrite_Offset) { + DidWrite(1, false); + DidWrite(1, false); + DidWrite(1, true); + } else if (offset == kCancelFileWriteBeforeCompletion_Offset) { + DidWrite(1, false); + cancel(); + DidWrite(1, false); + DidWrite(1, false); + DidFail(base::PLATFORM_FILE_ERROR_FAILED); // write completion + DidSucceed(); // cancel completion + } else if (offset == kCancelFileWriteAfterCompletion_Offset) { + DidWrite(1, false); + cancel(); + DidWrite(1, false); + DidWrite(1, false); + DidWrite(1, true); // write completion + DidFail(base::PLATFORM_FILE_ERROR_FAILED); // cancel completion + } else { + FAIL(); + } + } + virtual void DoCancel() OVERRIDE { received_cancel_ = true; } @@ -190,6 +228,9 @@ class FileWriterTest : public testing::Test, DISALLOW_COPY_AND_ASSIGN(FileWriterTest); }; + +// TODO(michaeln): crbug/174200, update the tests once blink is migrated. + TEST_F(FileWriterTest, BasicFileWrite) { // Call the webkit facing api. const GURL kBlobUrl("blob://bloburl/"); diff --git a/content/child/fileapi/webfilewriter_impl.cc b/content/child/fileapi/webfilewriter_impl.cc index 3347ea4..bcdc0d2 100644 --- a/content/child/fileapi/webfilewriter_impl.cc +++ b/content/child/fileapi/webfilewriter_impl.cc @@ -50,7 +50,21 @@ class WebFileWriterImpl::WriterBridge base::Bind(&WriterBridge::DidFinish, this)); } - void Write(const GURL& path, const GURL& blob_url, int64 offset, + void WriteDeprecated( + const GURL& path, const GURL& blob_url, int64 offset, + const WriteCallback& write_callback, + const StatusCallback& error_callback) { + write_callback_ = write_callback; + status_callback_ = error_callback; + if (!GetFileSystemDispatcher()) + return; + ChildThread::current()->file_system_dispatcher()->WriteDeprecated( + path, blob_url, offset, &request_id_, + base::Bind(&WriterBridge::DidWrite, this), + base::Bind(&WriterBridge::DidFinish, this)); + } + + void Write(const GURL& path, const std::string& id, int64 offset, const WriteCallback& write_callback, const StatusCallback& error_callback) { write_callback_ = write_callback; @@ -58,7 +72,7 @@ class WebFileWriterImpl::WriterBridge if (!GetFileSystemDispatcher()) return; ChildThread::current()->file_system_dispatcher()->Write( - path, blob_url, offset, &request_id_, + path, id, offset, &request_id_, base::Bind(&WriterBridge::DidWrite, this), base::Bind(&WriterBridge::DidFinish, this)); } @@ -139,14 +153,22 @@ void WebFileWriterImpl::DoTruncate(const GURL& path, int64 offset) { base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); } -void WebFileWriterImpl::DoWrite( +void WebFileWriterImpl::DoWriteDeprecated( const GURL& path, const GURL& blob_url, int64 offset) { - RunOnMainThread(base::Bind(&WriterBridge::Write, bridge_, + RunOnMainThread(base::Bind(&WriterBridge::WriteDeprecated, bridge_, path, blob_url, offset, base::Bind(&WebFileWriterImpl::DidWrite, AsWeakPtr()), base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); } +void WebFileWriterImpl::DoWrite( + const GURL& path, const std::string& blob_id, int64 offset) { + RunOnMainThread(base::Bind(&WriterBridge::Write, bridge_, + path, blob_id, offset, + base::Bind(&WebFileWriterImpl::DidWrite, AsWeakPtr()), + base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); +} + void WebFileWriterImpl::DoCancel() { RunOnMainThread(base::Bind(&WriterBridge::Cancel, bridge_, base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); diff --git a/content/child/fileapi/webfilewriter_impl.h b/content/child/fileapi/webfilewriter_impl.h index 69b979b..c4a5995 100644 --- a/content/child/fileapi/webfilewriter_impl.h +++ b/content/child/fileapi/webfilewriter_impl.h @@ -5,6 +5,8 @@ #ifndef CONTENT_CHILD_FILEAPI_WEBFILEWRITER_IMPL_H_ #define CONTENT_CHILD_FILEAPI_WEBFILEWRITER_IMPL_H_ +#include <string> + #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop_proxy.h" @@ -30,7 +32,9 @@ class WebFileWriterImpl : public WebFileWriterBase, protected: // WebFileWriterBase overrides virtual void DoTruncate(const GURL& path, int64 offset) OVERRIDE; - virtual void DoWrite(const GURL& path, const GURL& blob_url, + virtual void DoWriteDeprecated( + const GURL& path, const GURL& blob_url, int64 offset) OVERRIDE; + virtual void DoWrite(const GURL& path, const std::string& blob_id, int64 offset) OVERRIDE; virtual void DoCancel() OVERRIDE; diff --git a/content/child/webblobregistry_impl.cc b/content/child/webblobregistry_impl.cc index 421de95..b701c03 100644 --- a/content/child/webblobregistry_impl.cc +++ b/content/child/webblobregistry_impl.cc @@ -5,6 +5,7 @@ #include "content/child/webblobregistry_impl.h" #include "base/files/file_path.h" +#include "base/guid.h" #include "base/memory/ref_counted.h" #include "base/memory/shared_memory.h" #include "base/message_loop/message_loop.h" @@ -38,42 +39,11 @@ WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender* sender) WebBlobRegistryImpl::~WebBlobRegistryImpl() { } -void WebBlobRegistryImpl::SendDataForBlob(const WebURL& url, - const WebThreadSafeData& data) { - - if (data.size() == 0) - return; - if (data.size() < kLargeThresholdBytes) { - webkit_blob::BlobData::Item item; - item.SetToBytes(data.data(), data.size()); - sender_->Send(new BlobHostMsg_AppendBlobDataItem(url, item)); - } else { - // We handle larger amounts of data via SharedMemory instead of - // writing it directly to the IPC channel. - size_t shared_memory_size = std::min( - data.size(), kMaxSharedMemoryBytes); - scoped_ptr<base::SharedMemory> shared_memory( - ChildThread::AllocateSharedMemory(shared_memory_size, - sender_.get())); - CHECK(shared_memory.get()); +void WebBlobRegistryImpl::registerBlobData( + const WebKit::WebString& uuid, const WebKit::WebBlobData& data) { + const std::string uuid_str(uuid.utf8()); - size_t data_size = data.size(); - const char* data_ptr = data.data(); - while (data_size) { - size_t chunk_size = std::min(data_size, shared_memory_size); - memcpy(shared_memory->memory(), data_ptr, chunk_size); - sender_->Send(new BlobHostMsg_SyncAppendSharedMemory( - url, shared_memory->handle(), chunk_size)); - data_size -= chunk_size; - data_ptr += chunk_size; - } - } -} - -void WebBlobRegistryImpl::registerBlobURL( - const WebURL& url, WebBlobData& data) { - DCHECK(ChildThread::current()); - sender_->Send(new BlobHostMsg_StartBuilding(url)); + sender_->Send(new BlobHostMsg_StartBuilding(uuid_str)); size_t i = 0; WebBlobData::Item data_item; while (data.itemAt(i++, data_item)) { @@ -81,7 +51,7 @@ void WebBlobRegistryImpl::registerBlobURL( case WebBlobData::Item::TypeData: { // WebBlobData does not allow partial data items. DCHECK(!data_item.offset && data_item.length == -1); - SendDataForBlob(url, data_item.data); + SendDataForBlob(uuid_str, data_item.data); break; } case WebBlobData::Item::TypeFile: @@ -93,7 +63,7 @@ void WebBlobRegistryImpl::registerBlobURL( static_cast<uint64>(data_item.length), base::Time::FromDoubleT(data_item.expectedModificationTime)); sender_->Send( - new BlobHostMsg_AppendBlobDataItem(url, item)); + new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); } break; case WebBlobData::Item::TypeBlob: @@ -104,7 +74,7 @@ void WebBlobRegistryImpl::registerBlobURL( static_cast<uint64>(data_item.offset), static_cast<uint64>(data_item.length)); sender_->Send( - new BlobHostMsg_AppendBlobDataItem(url, item)); + new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); } break; case WebBlobData::Item::TypeURL: @@ -118,7 +88,7 @@ void WebBlobRegistryImpl::registerBlobURL( static_cast<uint64>(data_item.length), base::Time::FromDoubleT(data_item.expectedModificationTime)); sender_->Send( - new BlobHostMsg_AppendBlobDataItem(url, item)); + new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); } break; default: @@ -126,20 +96,87 @@ void WebBlobRegistryImpl::registerBlobURL( } } sender_->Send(new BlobHostMsg_FinishBuilding( - url, data.contentType().utf8().data())); + uuid_str, data.contentType().utf8().data())); +} + +void WebBlobRegistryImpl::addBlobDataRef(const WebString& uuid) { + sender_->Send(new BlobHostMsg_IncrementRefCount(uuid.utf8())); +} + +void WebBlobRegistryImpl::removeBlobDataRef(const WebString& uuid) { + sender_->Send(new BlobHostMsg_DecrementRefCount(uuid.utf8())); +} + +void WebBlobRegistryImpl::registerPublicBlobURL( + const WebURL& url, const WebString& uuid) { + sender_->Send(new BlobHostMsg_RegisterPublicURL(url, uuid.utf8())); +} + +void WebBlobRegistryImpl::revokePublicBlobURL(const WebURL& url) { + sender_->Send(new BlobHostMsg_RevokePublicURL(url)); +} + +void WebBlobRegistryImpl::SendDataForBlob(const std::string& uuid_str, + const WebThreadSafeData& data) { + + if (data.size() == 0) + return; + if (data.size() < kLargeThresholdBytes) { + webkit_blob::BlobData::Item item; + item.SetToBytes(data.data(), data.size()); + sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); + } else { + // We handle larger amounts of data via SharedMemory instead of + // writing it directly to the IPC channel. + size_t shared_memory_size = std::min( + data.size(), kMaxSharedMemoryBytes); + scoped_ptr<base::SharedMemory> shared_memory( + ChildThread::AllocateSharedMemory(shared_memory_size, + sender_.get())); + CHECK(shared_memory.get()); + + size_t data_size = data.size(); + const char* data_ptr = data.data(); + while (data_size) { + size_t chunk_size = std::min(data_size, shared_memory_size); + memcpy(shared_memory->memory(), data_ptr, chunk_size); + sender_->Send(new BlobHostMsg_SyncAppendSharedMemory( + uuid_str, shared_memory->handle(), chunk_size)); + data_size -= chunk_size; + data_ptr += chunk_size; + } + } +} + +// DEPRECATED, almost. Until blink is updated, we implement these older methods +// in terms of our newer blob storage system. We create a uuid for each 'data' +// we see and construct a mapping from the private blob urls we're given to +// that uuid. The mapping is maintained in the browser process. +// +// Chromium is setup to speak in terms of old-style private blob urls or +// new-style uuid identifiers. Once blink has been migrated support for +// the old-style will be deleted. Search for the term deprecated. + +void WebBlobRegistryImpl::registerBlobURL( + const WebURL& url, WebBlobData& data) { + std::string uuid = base::GenerateGUID(); + registerBlobData(WebKit::WebString::fromUTF8(uuid), data); + sender_->Send(new BlobHostMsg_DeprecatedRegisterBlobURL(url, uuid)); + sender_->Send(new BlobHostMsg_DecrementRefCount(uuid)); } void WebBlobRegistryImpl::registerBlobURL( const WebURL& url, const WebURL& src_url) { - DCHECK(ChildThread::current()); - sender_->Send(new BlobHostMsg_Clone(url, src_url)); + sender_->Send(new BlobHostMsg_DeprecatedCloneBlobURL(url, src_url)); } void WebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) { - DCHECK(ChildThread::current()); - sender_->Send(new BlobHostMsg_Remove(url)); + sender_->Send(new BlobHostMsg_DeprecatedRevokeBlobURL(url)); } + +// ------ streams stuff ----- + void WebBlobRegistryImpl::registerStreamURL( const WebURL& url, const WebString& content_type) { DCHECK(ChildThread::current()); diff --git a/content/child/webblobregistry_impl.h b/content/child/webblobregistry_impl.h index 87afcdb..1d6e54e 100644 --- a/content/child/webblobregistry_impl.h +++ b/content/child/webblobregistry_impl.h @@ -24,12 +24,23 @@ class WebBlobRegistryImpl : public WebKit::WebBlobRegistry { explicit WebBlobRegistryImpl(ThreadSafeSender* sender); virtual ~WebBlobRegistryImpl(); + virtual void registerBlobData(const WebKit::WebString& uuid, + const WebKit::WebBlobData& data); + virtual void addBlobDataRef(const WebKit::WebString& uuid); + virtual void removeBlobDataRef(const WebKit::WebString& uuid); + virtual void registerPublicBlobURL(const WebKit::WebURL&, + const WebKit::WebString& uuid); + virtual void revokePublicBlobURL(const WebKit::WebURL&); + + // DEPRECATED + // TODO(michaeln): crbug/174200 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); + // Additional support for Streams. virtual void registerStreamURL(const WebKit::WebURL& url, const WebKit::WebString& content_type); virtual void registerStreamURL(const WebKit::WebURL& url, @@ -41,7 +52,7 @@ class WebBlobRegistryImpl : public WebKit::WebBlobRegistry { virtual void unregisterStreamURL(const WebKit::WebURL& url); private: - void SendDataForBlob(const WebKit::WebURL& url, + void SendDataForBlob(const std::string& uuid_str, const WebKit::WebThreadSafeData& data); scoped_refptr<ThreadSafeSender> sender_; diff --git a/content/common/fileapi/file_system_messages.h b/content/common/fileapi/file_system_messages.h index a2d2500..12a3f17 100644 --- a/content/common/fileapi/file_system_messages.h +++ b/content/common/fileapi/file_system_messages.h @@ -118,12 +118,19 @@ IPC_MESSAGE_CONTROL2(FileSystemHostMsg_ReadDirectory, GURL /* path */) // WebFileWriter::write() message. -IPC_MESSAGE_CONTROL4(FileSystemHostMsg_Write, +IPC_MESSAGE_CONTROL4(FileSystemHostMsg_WriteDeprecated, int /* request id */, GURL /* file path */, GURL /* blob URL */, int64 /* position */) +// WebFileWriter::write() message. +IPC_MESSAGE_CONTROL4(FileSystemHostMsg_Write, + int /* request id */, + GURL /* file path */, + std::string /* blob uuid */, + int64 /* position */) + // WebFileWriter::truncate() message. IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Truncate, int /* request id */, diff --git a/content/common/fileapi/webblob_messages.h b/content/common/fileapi/webblob_messages.h index 51c44cb..92a9816 100644 --- a/content/common/fileapi/webblob_messages.h +++ b/content/common/fileapi/webblob_messages.h @@ -16,35 +16,40 @@ // Blob messages sent from the renderer to the browser. -// Registers a blob as being built. IPC_MESSAGE_CONTROL1(BlobHostMsg_StartBuilding, - GURL /* url */) - -// Appends data to a blob being built. + std::string /*uuid */) IPC_MESSAGE_CONTROL2(BlobHostMsg_AppendBlobDataItem, - GURL /* url */, + std::string /* uuid */, webkit_blob::BlobData::Item) - -// Appends data to a blob being built. IPC_SYNC_MESSAGE_CONTROL3_0(BlobHostMsg_SyncAppendSharedMemory, - GURL /* url */, + std::string /*uuid*/, base::SharedMemoryHandle, size_t /* buffer size */) - -// Finishes building a blob. IPC_MESSAGE_CONTROL2(BlobHostMsg_FinishBuilding, - GURL /* url */, + std::string /* uuid */, std::string /* content_type */) -// Creates a new blob that's a clone of an existing src blob. The source blob -// must be fully built. -IPC_MESSAGE_CONTROL2(BlobHostMsg_Clone, - GURL /* url */, - GURL /* src_url */) +IPC_MESSAGE_CONTROL1(BlobHostMsg_IncrementRefCount, + std::string /* uuid */) +IPC_MESSAGE_CONTROL1(BlobHostMsg_DecrementRefCount, + std::string /* uuid */) +IPC_MESSAGE_CONTROL2(BlobHostMsg_RegisterPublicURL, + GURL, + std::string /* uuid */) +IPC_MESSAGE_CONTROL1(BlobHostMsg_RevokePublicURL, + GURL) + +// Temporary support for mapping old style blobUrls to new style uuids. +IPC_MESSAGE_CONTROL2(BlobHostMsg_DeprecatedRegisterBlobURL, + GURL, + std::string /* uuid */) +IPC_MESSAGE_CONTROL2(BlobHostMsg_DeprecatedCloneBlobURL, + GURL, + GURL) +IPC_MESSAGE_CONTROL1(BlobHostMsg_DeprecatedRevokeBlobURL, + GURL) + -// Removes a blob. -IPC_MESSAGE_CONTROL1(BlobHostMsg_Remove, - GURL /* url */) // Stream messages sent from the renderer to the browser. diff --git a/content/common/page_state_serialization.cc b/content/common/page_state_serialization.cc index 4ba7345..530726b 100644 --- a/content/common/page_state_serialization.cc +++ b/content/common/page_state_serialization.cc @@ -51,17 +51,18 @@ void AppendURLRangeToHttpBody(ExplodedHttpBody* http_body, double file_modification_time) { ExplodedHttpBodyElement element; element.type = WebKit::WebHTTPBody::Element::TypeURL; - element.url = url; + element.filesystem_url = url; element.file_start = file_start; element.file_length = file_length; element.file_modification_time = file_modification_time; http_body->elements.push_back(element); } -void AppendBlobToHttpBody(ExplodedHttpBody* http_body, const GURL& url) { +void DeprecatedAppendBlobToHttpBody(ExplodedHttpBody* http_body, + const GURL& url) { ExplodedHttpBodyElement element; element.type = WebKit::WebHTTPBody::Element::TypeBlob; - element.url = url; + element.deprecated_blob_url = url; http_body->elements.push_back(element); } @@ -396,12 +397,13 @@ void WriteHttpBody(const ExplodedHttpBody& http_body, SerializeObject* obj) { WriteInteger64(element.file_length, obj); WriteReal(element.file_modification_time, obj); } else if (element.type == WebKit::WebHTTPBody::Element::TypeURL) { - WriteGURL(element.url, obj); + WriteGURL(element.filesystem_url, obj); WriteInteger64(element.file_start, obj); WriteInteger64(element.file_length, obj); WriteReal(element.file_modification_time, obj); } else { - WriteGURL(element.url, obj); + DCHECK(element.type == WebKit::WebHTTPBody::Element::TypeBlob); + WriteGURL(element.deprecated_blob_url, obj); } } WriteInteger64(http_body.identifier, obj); @@ -442,7 +444,7 @@ void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) { file_modification_time); } else if (type == WebKit::WebHTTPBody::Element::TypeBlob) { GURL blob_url = ReadGURL(obj); - AppendBlobToHttpBody(http_body, blob_url); + DeprecatedAppendBlobToHttpBody(http_body, blob_url); } } http_body->identifier = ReadInteger64(obj); diff --git a/content/common/page_state_serialization.h b/content/common/page_state_serialization.h index c5057ac..24291ef 100644 --- a/content/common/page_state_serialization.h +++ b/content/common/page_state_serialization.h @@ -19,10 +19,11 @@ struct CONTENT_EXPORT ExplodedHttpBodyElement { WebKit::WebHTTPBody::Element::Type type; std::string data; base::NullableString16 file_path; - GURL url; + GURL filesystem_url; int64 file_start; int64 file_length; double file_modification_time; + GURL deprecated_blob_url; ExplodedHttpBodyElement(); ~ExplodedHttpBodyElement(); diff --git a/content/common/page_state_serialization_unittest.cc b/content/common/page_state_serialization_unittest.cc index e899867..07b9cf8 100644 --- a/content/common/page_state_serialization_unittest.cc +++ b/content/common/page_state_serialization_unittest.cc @@ -47,11 +47,12 @@ void ExpectEquality(const ExplodedHttpBodyElement& a, EXPECT_EQ(a.type, b.type); EXPECT_EQ(a.data, b.data); EXPECT_EQ(a.file_path, b.file_path); - EXPECT_EQ(a.url, b.url); + EXPECT_EQ(a.filesystem_url, b.filesystem_url); EXPECT_EQ(a.file_start, b.file_start); EXPECT_EQ(a.file_length, b.file_length); if (!(isnan(a.file_modification_time) && isnan(b.file_modification_time))) EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time); + EXPECT_EQ(a.deprecated_blob_url, b.deprecated_blob_url); } template <> diff --git a/content/common/resource_messages.cc b/content/common/resource_messages.cc index 0bfaa07..72127b9 100644 --- a/content/common/resource_messages.cc +++ b/content/common/resource_messages.cc @@ -50,7 +50,7 @@ void ParamTraits<webkit_common::DataElement>::Write( break; } case webkit_common::DataElement::TYPE_FILE_FILESYSTEM: { - WriteParam(m, p.url()); + WriteParam(m, p.filesystem_url()); WriteParam(m, p.offset()); WriteParam(m, p.length()); WriteParam(m, p.expected_modification_time()); @@ -58,7 +58,8 @@ void ParamTraits<webkit_common::DataElement>::Write( } default: { DCHECK(p.type() == webkit_common::DataElement::TYPE_BLOB); - WriteParam(m, p.url()); + WriteParam(m, p.blob_uuid()); + WriteParam(m, p.blob_url()); WriteParam(m, p.offset()); WriteParam(m, p.length()); break; @@ -114,15 +115,21 @@ bool ParamTraits<webkit_common::DataElement>::Read( } default: { DCHECK(type == webkit_common::DataElement::TYPE_BLOB); + std::string blob_uuid; GURL blob_url; uint64 offset, length; + if (!ReadParam(m, iter, &blob_uuid)) + return false; if (!ReadParam(m, iter, &blob_url)) return false; if (!ReadParam(m, iter, &offset)) return false; if (!ReadParam(m, iter, &length)) return false; - r->SetToBlobUrlRange(blob_url, offset, length); + if (!blob_uuid.empty()) + r->SetToBlobRange(blob_uuid, offset, length); + else + r->SetToBlobUrlRange(blob_url, offset, length); break; } } diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 1074d32..92879c1 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -477,7 +477,6 @@ '../webkit/browser/appcache/mock_appcache_storage.h', '../webkit/browser/appcache/mock_appcache_storage_unittest.cc', '../webkit/browser/blob/blob_storage_context_unittest.cc', - '../webkit/browser/blob/blob_storage_controller_unittest.cc', '../webkit/browser/blob/blob_url_request_job_unittest.cc', '../webkit/browser/blob/local_file_stream_reader_unittest.cc', '../webkit/browser/blob/mock_blob_url_request_context.cc', diff --git a/content/public/renderer/history_item_serialization.cc b/content/public/renderer/history_item_serialization.cc index 80c305e..5426557 100644 --- a/content/public/renderer/history_item_serialization.cc +++ b/content/public/renderer/history_item_serialization.cc @@ -42,13 +42,13 @@ void ToExplodedHttpBodyElement(const WebHTTPBody::Element& input, output->file_modification_time = input.modificationTime; break; case WebHTTPBody::Element::TypeURL: - output->url = input.url; + output->filesystem_url = input.url; output->file_start = input.fileStart; output->file_length = input.fileLength; output->file_modification_time = input.modificationTime; break; case WebHTTPBody::Element::TypeBlob: - output->url = input.url; + output->deprecated_blob_url = input.blobURL; break; } } @@ -68,13 +68,13 @@ void AppendHTTPBodyElement(const ExplodedHttpBodyElement& element, break; case WebHTTPBody::Element::TypeURL: http_body->appendURLRange( - element.url, + element.filesystem_url, element.file_start, element.file_length, element.file_modification_time); break; case WebHTTPBody::Element::TypeBlob: - http_body->appendBlob(element.url); + http_body->appendBlob(element.deprecated_blob_url); break; } } diff --git a/webkit/browser/blob/blob_data_handle.h b/webkit/browser/blob/blob_data_handle.h index 25eeefe..5f870f2 100644 --- a/webkit/browser/blob/blob_data_handle.h +++ b/webkit/browser/blob/blob_data_handle.h @@ -43,6 +43,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobDataHandle BlobData* blob_data_; // Intentionally a raw ptr to a non-thread-safe ref. base::WeakPtr<BlobStorageContext> context_; scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(BlobDataHandle); }; } // namespace webkit_blob diff --git a/webkit/browser/blob/blob_storage_context.cc b/webkit/browser/blob/blob_storage_context.cc index 4a02607..bc8fa64 100644 --- a/webkit/browser/blob/blob_storage_context.cc +++ b/webkit/browser/blob/blob_storage_context.cc @@ -94,6 +94,14 @@ scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob( return handle.Pass(); } +std::string BlobStorageContext::LookupUuidFromDeprecatedURL( + const GURL& url) { + BlobURLMap::const_iterator found = deprecated_blob_urls_.find(url); + if (found == deprecated_blob_urls_.end()) + return std::string(); + return found->second; +} + void BlobStorageContext::StartBuildingBlob(const std::string& uuid) { DCHECK(!IsInUse(uuid) && !uuid.empty()); blob_map_[uuid] = BlobMapEntry(1, BEING_BUILT, new BlobData(uuid)); @@ -222,6 +230,21 @@ void BlobStorageContext::RevokePublicBlobURL(const GURL& blob_url) { public_blob_urls_.erase(blob_url); } +void BlobStorageContext::DeprecatedRegisterPrivateBlobURL( + const GURL& url, const std::string& uuid) { + if (!IsInUse(uuid)) + return; + IncrementBlobRefCount(uuid); + deprecated_blob_urls_[url] = uuid; +} + +void BlobStorageContext::DeprecatedRevokePrivateBlobURL(const GURL& url) { + if (deprecated_blob_urls_.find(url) == deprecated_blob_urls_.end()) + return; + DecrementBlobRefCount(deprecated_blob_urls_[url]); + deprecated_blob_urls_.erase(url); +} + bool BlobStorageContext::ExpandStorageItems( BlobData* target_blob_data, BlobData* src_blob_data, uint64 offset, uint64 length) { diff --git a/webkit/browser/blob/blob_storage_context.h b/webkit/browser/blob/blob_storage_context.h index c9747ae..eec1fee 100644 --- a/webkit/browser/blob/blob_storage_context.h +++ b/webkit/browser/blob/blob_storage_context.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/webkit_storage_browser_export.h" #include "webkit/common/blob/blob_data.h" @@ -42,9 +43,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext // blob cannot be added due to memory consumption, returns NULL. scoped_ptr<BlobDataHandle> AddFinishedBlob(const BlobData* blob_data); + // Temporary support for mapping oldstyle blobUrls to new style uuids. + std::string LookupUuidFromDeprecatedURL(const GURL& url); + private: friend class BlobDataHandle; friend class BlobStorageHost; + friend class ViewBlobInternalsJob; enum EntryFlags { BEING_BUILT = 1 << 0, @@ -75,6 +80,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext void RegisterPublicBlobURL(const GURL& url, const std::string& uuid); void RevokePublicBlobURL(const GURL& url); + // Temporary support for mapping old style blobUrls to new style uuids. + void DeprecatedRegisterPrivateBlobURL(const GURL& url, + const std::string& uuid); + void DeprecatedRevokePrivateBlobURL(const GURL& url); + bool ExpandStorageItems(BlobData* target_blob_data, BlobData* src_blob_data, uint64 offset, @@ -96,6 +106,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext BlobMap blob_map_; BlobURLMap public_blob_urls_; + BlobURLMap deprecated_blob_urls_; // Used to keep track of how much memory is being utitlized for blob data, // we count only the items of TYPE_DATA which are held in memory and not diff --git a/webkit/browser/blob/blob_storage_context_unittest.cc b/webkit/browser/blob/blob_storage_context_unittest.cc index 5ce1545..e2c115c 100644 --- a/webkit/browser/blob/blob_storage_context_unittest.cc +++ b/webkit/browser/blob/blob_storage_context_unittest.cc @@ -203,4 +203,6 @@ TEST(BlobStorageContextTest, EarlyContextDeletion) { EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); } +// TODO(michaeln): tests for the depcrecated url stuff + } // namespace webkit_blob diff --git a/webkit/browser/blob/blob_storage_controller.cc b/webkit/browser/blob/blob_storage_controller.cc deleted file mode 100644 index f5dd60e..0000000 --- a/webkit/browser/blob/blob_storage_controller.cc +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2012 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/browser/blob/blob_storage_controller.h" - -#include "base/logging.h" -#include "url/gurl.h" -#include "webkit/common/blob/blob_data.h" - -namespace webkit_blob { - -namespace { - -// We can't use GURL directly for these hash fragment manipulations -// since it doesn't have specific knowlege of the BlobURL format. GURL -// treats BlobURLs as if they were PathURLs which don't support hash -// fragments. - -bool BlobUrlHasRef(const GURL& url) { - return url.spec().find('#') != std::string::npos; -} - -GURL ClearBlobUrlRef(const GURL& url) { - size_t hash_pos = url.spec().find('#'); - if (hash_pos == std::string::npos) - return url; - return GURL(url.spec().substr(0, hash_pos)); -} - -static const int64 kMaxMemoryUsage = 1024 * 1024 * 1024; // 1G - -} // namespace - -BlobStorageController::BlobStorageController() - : memory_usage_(0) { -} - -BlobStorageController::~BlobStorageController() { -} - -void BlobStorageController::StartBuildingBlob(const GURL& url) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - BlobData* blob_data = new BlobData; - unfinalized_blob_map_[url.spec()] = blob_data; - IncrementBlobDataUsage(blob_data); -} - -void BlobStorageController::AppendBlobDataItem( - const GURL& url, const BlobData::Item& item) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - BlobMap::iterator found = unfinalized_blob_map_.find(url.spec()); - if (found == unfinalized_blob_map_.end()) - return; - BlobData* target_blob_data = found->second.get(); - DCHECK(target_blob_data); - - memory_usage_ -= target_blob_data->GetMemoryUsage(); - - // 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. - // 3) The FileSystem File item is denoted by the FileSystem URL, 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. - - DCHECK(item.length() > 0); - switch (item.type()) { - case BlobData::Item::TYPE_BYTES: - DCHECK(!item.offset()); - target_blob_data->AppendData(item.bytes(), item.length()); - break; - case BlobData::Item::TYPE_FILE: - AppendFileItem(target_blob_data, - item.path(), - item.offset(), - item.length(), - item.expected_modification_time()); - break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: - AppendFileSystemFileItem(target_blob_data, - item.url(), - item.offset(), - item.length(), - item.expected_modification_time()); - break; - case BlobData::Item::TYPE_BLOB: { - BlobData* src_blob_data = GetBlobDataFromUrl(item.url()); - DCHECK(src_blob_data); - if (src_blob_data) - AppendStorageItems(target_blob_data, - src_blob_data, - item.offset(), - item.length()); - break; - } - default: - NOTREACHED(); - break; - } - - memory_usage_ += target_blob_data->GetMemoryUsage(); - - // If we're using too much memory, drop this blob. - // TODO(michaeln): Blob memory storage does not yet spill over to disk, - // until it does, we'll prevent memory usage over a max amount. - if (memory_usage_ > kMaxMemoryUsage) - RemoveBlob(url); -} - -void BlobStorageController::FinishBuildingBlob( - const GURL& url, const std::string& content_type) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - BlobMap::iterator found = unfinalized_blob_map_.find(url.spec()); - if (found == unfinalized_blob_map_.end()) - return; - found->second->set_content_type(content_type); - blob_map_[url.spec()] = found->second; - unfinalized_blob_map_.erase(found); -} - -void BlobStorageController::AddFinishedBlob(const GURL& url, - const BlobData* data) { - StartBuildingBlob(url); - for (std::vector<BlobData::Item>::const_iterator iter = - data->items().begin(); - iter != data->items().end(); ++iter) { - AppendBlobDataItem(url, *iter); - } - FinishBuildingBlob(url, data->content_type()); -} - -void BlobStorageController::CloneBlob( - const GURL& url, const GURL& src_url) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - - BlobData* blob_data = GetBlobDataFromUrl(src_url); - DCHECK(blob_data); - if (!blob_data) - return; - - blob_map_[url.spec()] = blob_data; - IncrementBlobDataUsage(blob_data); -} - -void BlobStorageController::RemoveBlob(const GURL& url) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - - if (!RemoveFromMapHelper(&unfinalized_blob_map_, url)) - RemoveFromMapHelper(&blob_map_, url); -} - -bool BlobStorageController::RemoveFromMapHelper( - BlobMap* map, const GURL& url) { - BlobMap::iterator found = map->find(url.spec()); - if (found == map->end()) - return false; - if (DecrementBlobDataUsage(found->second.get())) - memory_usage_ -= found->second->GetMemoryUsage(); - map->erase(found); - return true; -} - - -BlobData* BlobStorageController::GetBlobDataFromUrl(const GURL& url) { - BlobMap::iterator found = blob_map_.find( - BlobUrlHasRef(url) ? ClearBlobUrlRef(url).spec() : url.spec()); - return (found != blob_map_.end()) ? found->second.get() : NULL; -} - -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::Item::TYPE_BYTES) { - target_blob_data->AppendData( - iter->bytes() + static_cast<size_t>(iter->offset() + offset), - static_cast<uint32>(new_length)); - } else if (iter->type() == BlobData::Item::TYPE_FILE) { - AppendFileItem(target_blob_data, - iter->path(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); - } else { - DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM); - AppendFileSystemFileItem(target_blob_data, - iter->url(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); - } - length -= new_length; - offset = 0; - } -} - -void BlobStorageController::AppendFileItem( - BlobData* target_blob_data, - const base::FilePath& file_path, uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - target_blob_data->AppendFile(file_path, offset, length, - expected_modification_time); - - // It may be a temporary file that should be deleted when no longer needed. - scoped_refptr<ShareableFileReference> shareable_file = - ShareableFileReference::Get(file_path); - if (shareable_file.get()) - target_blob_data->AttachShareableFileReference(shareable_file.get()); -} - -void BlobStorageController::AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& url, uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - target_blob_data->AppendFileSystemFile(url, offset, length, - expected_modification_time); -} - -void BlobStorageController::IncrementBlobDataUsage(BlobData* blob_data) { - blob_data_usage_count_[blob_data] += 1; -} - -bool BlobStorageController::DecrementBlobDataUsage(BlobData* blob_data) { - BlobDataUsageMap::iterator found = blob_data_usage_count_.find(blob_data); - DCHECK(found != blob_data_usage_count_.end()); - if (--(found->second)) - return false; // Still in use - blob_data_usage_count_.erase(found); - return true; -} - -} // namespace webkit_blob diff --git a/webkit/browser/blob/blob_storage_controller.h b/webkit/browser/blob/blob_storage_controller.h deleted file mode 100644 index 03dfb08..0000000 --- a/webkit/browser/blob/blob_storage_controller.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 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_BROWSER_BLOB_BLOB_STORAGE_CONTROLLER_H_ -#define WEBKIT_BROWSER_BLOB_BLOB_STORAGE_CONTROLLER_H_ - -#include <map> -#include <string> - -#include "base/containers/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "base/process/process.h" -#include "webkit/browser/webkit_storage_browser_export.h" -#include "webkit/common/blob/blob_data.h" - -class GURL; - -namespace base { -class FilePath; -class Time; -} - -namespace webkit_blob { - -// This class handles the logistics of blob Storage within the browser process. -class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageController { - public: - BlobStorageController(); - ~BlobStorageController(); - - void StartBuildingBlob(const GURL& url); - void AppendBlobDataItem(const GURL& url, const BlobData::Item& data_item); - void FinishBuildingBlob(const GURL& url, const std::string& content_type); - void AddFinishedBlob(const GURL& url, const BlobData* blob_data); - void CloneBlob(const GURL& url, const GURL& src_url); - void RemoveBlob(const GURL& url); - BlobData* GetBlobDataFromUrl(const GURL& url); - - private: - friend class ViewBlobInternalsJob; - - typedef base::hash_map<std::string, scoped_refptr<BlobData> > BlobMap; - typedef std::map<BlobData*, int> BlobDataUsageMap; - - void AppendStorageItems(BlobData* target_blob_data, - BlobData* src_blob_data, - uint64 offset, - uint64 length); - void AppendFileItem(BlobData* target_blob_data, - const base::FilePath& file_path, uint64 offset, - uint64 length, - const base::Time& expected_modification_time); - void AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& url, uint64 offset, uint64 length, - const base::Time& expected_modification_time); - - bool RemoveFromMapHelper(BlobMap* map, const GURL& url); - - void IncrementBlobDataUsage(BlobData* blob_data); - // Returns true if no longer in use. - bool DecrementBlobDataUsage(BlobData* blob_data); - - BlobMap blob_map_; - BlobMap unfinalized_blob_map_; - - // Used to keep track of how much memory is being utitlized for blob data, - // we count only the items of TYPE_DATA which are held in memory and not - // items of TYPE_FILE. - int64 memory_usage_; - - // Multiple urls can refer to the same blob data, this map keeps track of - // how many urls refer to a BlobData. - BlobDataUsageMap blob_data_usage_count_; - - DISALLOW_COPY_AND_ASSIGN(BlobStorageController); -}; - -} // namespace webkit_blob - -#endif // WEBKIT_BROWSER_BLOB_BLOB_STORAGE_CONTROLLER_H_ diff --git a/webkit/browser/blob/blob_storage_controller_unittest.cc b/webkit/browser/blob/blob_storage_controller_unittest.cc deleted file mode 100644 index fbef876..0000000 --- a/webkit/browser/blob/blob_storage_controller_unittest.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2011 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/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/blob/blob_storage_controller.h" -#include "webkit/common/blob/blob_data.h" - -namespace webkit_blob { - -TEST(BlobStorageControllerTest, RegisterBlobUrl) { - // Setup a set of blob data for testing. - base::Time time1, time2; - base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); - base::Time::FromString("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(base::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(base::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("a2___", 2); - canonicalized_blob_data2->AppendFile( - base::FilePath(FILE_PATH_LITERAL("File1.txt")), - 10, 98, time1); - canonicalized_blob_data2->AppendFile( - base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); - - BlobStorageController blob_storage_controller; - - // Test registering a blob URL referring to the blob data containing only - // data and file. - GURL blob_url1("blob://url_1"); - blob_storage_controller.AddFinishedBlob(blob_url1, blob_data1.get()); - - BlobData* blob_data_found = - blob_storage_controller.GetBlobDataFromUrl(blob_url1); - ASSERT_TRUE(blob_data_found != NULL); - EXPECT_TRUE(*blob_data_found == *blob_data1.get()); - - // Test registering a blob URL referring to the blob data containing data, - // file and blob. - GURL blob_url2("blob://url_2"); - blob_storage_controller.AddFinishedBlob(blob_url2, blob_data2.get()); - - blob_data_found = blob_storage_controller.GetBlobDataFromUrl(blob_url2); - ASSERT_TRUE(blob_data_found != NULL); - EXPECT_TRUE(*blob_data_found == *canonicalized_blob_data2.get()); - - // Test registering a blob URL referring to existent blob URL. - GURL blob_url3("blob://url_3"); - blob_storage_controller.CloneBlob(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.get()); - - // Test unregistering a blob URL. - blob_storage_controller.RemoveBlob(blob_url3); - blob_data_found = blob_storage_controller.GetBlobDataFromUrl(blob_url3); - EXPECT_TRUE(!blob_data_found); -} - -} // namespace webkit_blob diff --git a/webkit/browser/blob/blob_storage_host.cc b/webkit/browser/blob/blob_storage_host.cc index eebf3fb..9d3ddb9 100644 --- a/webkit/browser/blob/blob_storage_host.cc +++ b/webkit/browser/blob/blob_storage_host.cc @@ -5,6 +5,7 @@ #include "webkit/browser/blob/blob_storage_host.h" #include "base/sequenced_task_runner.h" +#include "base/strings/string_util.h" #include "url/gurl.h" #include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/blob/blob_storage_context.h" @@ -27,6 +28,10 @@ BlobStorageHost::~BlobStorageHost() { for (int i = 0; i < iter->second; ++i) context_->DecrementBlobRefCount(iter->first); } + for (std::set<GURL>::iterator iter = private_blob_urls_.begin(); + iter != private_blob_urls_.end(); ++iter) { + context_->DeprecatedRevokePrivateBlobURL(*iter); + } } bool BlobStorageHost::StartBuildingBlob(const std::string& uuid) { @@ -98,6 +103,56 @@ bool BlobStorageHost::RevokePublicBlobURL(const GURL& blob_url) { return true; } +namespace { +bool IsPrivateBlobURL(const GURL& url) { + return StartsWithASCII(url.spec(), "blob:blobinternal", true); +} +} + +void BlobStorageHost::DeprecatedRegisterBlobURL( + const GURL& private_url, const std::string& uuid) { + DCHECK(IsPrivateBlobURL(private_url)); + if (!context_.get()) + return; + context_->DeprecatedRegisterPrivateBlobURL(private_url, uuid); + private_blob_urls_.insert(private_url); +} + +void BlobStorageHost::DeprecatedCloneBlobURL( + const GURL& url, const GURL& src_private_url) { + // This method is used in two ways. + // 1. During serialization/deserialization to 'clone' an existing blob. + // In this case the src and dest urls are 'private' blob urls. + // 2. To register public blob urls. In this case the dest url is a + // 'public' blob url. + DCHECK(IsPrivateBlobURL(src_private_url)); + if (!context_.get()) + return; + std::string uuid = context_->LookupUuidFromDeprecatedURL(src_private_url); + if (uuid.empty()) + return; + if (IsPrivateBlobURL(url)) { + DeprecatedRegisterBlobURL(url, uuid); + } else { + // Temporarily bump the refcount so the uuid passes the InUse + // check inside the RegisterPublicBlobURL method. + ignore_result(IncrementBlobRefCount(uuid)); + ignore_result(RegisterPublicBlobURL(url, uuid)); + ignore_result(DecrementBlobRefCount(uuid)); + } +} + +void BlobStorageHost::DeprecatedRevokeBlobURL(const GURL& url) { + if (!context_.get()) + return; + if (IsPrivateBlobURL(url)) { + context_->DeprecatedRevokePrivateBlobURL(url); + private_blob_urls_.erase(url); + } else { + ignore_result(RevokePublicBlobURL(url)); + } +} + bool BlobStorageHost::IsInUseInHost(const std::string& uuid) { return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end(); } diff --git a/webkit/browser/blob/blob_storage_host.h b/webkit/browser/blob/blob_storage_host.h index 954c32c..890db3a 100644 --- a/webkit/browser/blob/blob_storage_host.h +++ b/webkit/browser/blob/blob_storage_host.h @@ -47,6 +47,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageHost { const std::string& uuid) WARN_UNUSED_RESULT; bool RevokePublicBlobURL(const GURL& blob_url) WARN_UNUSED_RESULT; + // Temporary support for mapping old style private blob urls to uuids. + void DeprecatedRegisterBlobURL(const GURL& private_url, + const std::string& uuid); + void DeprecatedCloneBlobURL(const GURL& url, + const GURL& src_private_url); + void DeprecatedRevokeBlobURL(const GURL& url); + private: typedef std::map<std::string, int> BlobReferenceMap; @@ -61,7 +68,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageHost { // The set of public blob urls coined by this consumer. std::set<GURL> public_blob_urls_; + // And private deprecated blob urls. + std::set<GURL> private_blob_urls_; + base::WeakPtr<BlobStorageContext> context_; + + DISALLOW_COPY_AND_ASSIGN(BlobStorageHost); }; } // namespace webkit_blob diff --git a/webkit/browser/blob/blob_url_request_job.cc b/webkit/browser/blob/blob_url_request_job.cc index a845fc9..28002b5 100644 --- a/webkit/browser/blob/blob_url_request_job.cc +++ b/webkit/browser/blob/blob_url_request_job.cc @@ -558,7 +558,8 @@ void BlobURLRequestJob::CreateFileStreamReader(size_t index, break; case BlobData::Item::TYPE_FILE_FILESYSTEM: reader = file_system_context_->CreateFileStreamReader( - fileapi::FileSystemURL(file_system_context_->CrackURL(item.url())), + fileapi::FileSystemURL( + file_system_context_->CrackURL(item.filesystem_url())), item.offset() + additional_offset, item.expected_modification_time()).release(); break; diff --git a/webkit/browser/blob/blob_url_request_job_factory.cc b/webkit/browser/blob/blob_url_request_job_factory.cc index cc600d1..1819838 100644 --- a/webkit/browser/blob/blob_url_request_job_factory.cc +++ b/webkit/browser/blob/blob_url_request_job_factory.cc @@ -7,44 +7,65 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/message_loop/message_loop_proxy.h" -#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/blob/blob_url_request_job.h" #include "webkit/browser/fileapi/file_system_context.h" namespace webkit_blob { +namespace { + +int kUserDataKey; // The value is not important, the addr is a key. + +BlobDataHandle* GetRequestedBlobDataHandle(net::URLRequest* request) { + return static_cast<BlobDataHandle*>(request->GetUserData(&kUserDataKey)); +} + +} // namespace + +// static +net::URLRequest* BlobProtocolHandler::CreateBlobRequest( + scoped_ptr<BlobDataHandle> blob_data_handle, + const net::URLRequestContext* request_context, + net::URLRequest::Delegate* request_delegate) { + const GURL kBlobUrl("blob://see_user_data/"); + net::URLRequest* request = request_context->CreateRequest( + kBlobUrl, request_delegate); + SetRequestedBlobDataHandle(request, blob_data_handle.Pass()); + return request; +} + +// static +void BlobProtocolHandler::SetRequestedBlobDataHandle( + net::URLRequest* request, + scoped_ptr<BlobDataHandle> blob_data_handle) { + request->SetUserData(&kUserDataKey, blob_data_handle.release()); +} + BlobProtocolHandler::BlobProtocolHandler( - webkit_blob::BlobStorageController* blob_storage_controller, fileapi::FileSystemContext* file_system_context, base::MessageLoopProxy* loop_proxy) - : blob_storage_controller_(blob_storage_controller), - file_system_context_(file_system_context), + : file_system_context_(file_system_context), file_loop_proxy_(loop_proxy) { - DCHECK(blob_storage_controller_); - DCHECK(file_system_context_.get()); - DCHECK(file_loop_proxy_.get()); } -BlobProtocolHandler::~BlobProtocolHandler() {} +BlobProtocolHandler::~BlobProtocolHandler() { +} net::URLRequestJob* BlobProtocolHandler::MaybeCreateJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) const { - scoped_refptr<webkit_blob::BlobData> data = LookupBlobData(request); - if (!data.get()) { - // This request is not coming through resource dispatcher host. - data = blob_storage_controller_->GetBlobDataFromUrl(request->url()); - } - return new webkit_blob::BlobURLRequestJob(request, - network_delegate, - data.get(), - file_system_context_.get(), - file_loop_proxy_.get()); + return new webkit_blob::BlobURLRequestJob( + request, network_delegate, LookupBlobData(request), + file_system_context_, file_loop_proxy_); } scoped_refptr<webkit_blob::BlobData> BlobProtocolHandler::LookupBlobData(net::URLRequest* request) const { + BlobDataHandle* blob_data_handle = GetRequestedBlobDataHandle(request); + if (blob_data_handle) + return blob_data_handle->data(); return NULL; } diff --git a/webkit/browser/blob/blob_url_request_job_factory.h b/webkit/browser/blob/blob_url_request_job_factory.h index 2a78c95..e40eb5d 100644 --- a/webkit/browser/blob/blob_url_request_job_factory.h +++ b/webkit/browser/blob/blob_url_request_job_factory.h @@ -7,6 +7,8 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/url_request/url_request.h" #include "net/url_request/url_request_job_factory.h" #include "webkit/browser/webkit_storage_browser_export.h" @@ -19,20 +21,30 @@ class FileSystemContext; } // namespace fileapi namespace net { -class URLRequest; +class URLRequestContext; } // namespace net namespace webkit_blob { class BlobData; -class BlobStorageController; +class BlobDataHandle; class WEBKIT_STORAGE_BROWSER_EXPORT BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: - // |controller|'s lifetime should exceed the lifetime of the ProtocolHandler. - BlobProtocolHandler(BlobStorageController* blob_storage_controller, - fileapi::FileSystemContext* file_system_context, + // A helper to manufacture an URLRequest to retrieve the given blob. + static net::URLRequest* CreateBlobRequest( + scoped_ptr<BlobDataHandle> blob_data_handle, + const net::URLRequestContext* request_context, + net::URLRequest::Delegate* request_delegate); + + // This class ignores the request's URL and uses the value given + // to SetRequestedBlobDataHandle instead. + static void SetRequestedBlobDataHandle( + net::URLRequest* request, + scoped_ptr<BlobDataHandle> blob_data_handle); + + BlobProtocolHandler(fileapi::FileSystemContext* file_system_context, base::MessageLoopProxy* file_loop_proxy); virtual ~BlobProtocolHandler(); @@ -41,12 +53,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobProtocolHandler net::NetworkDelegate* network_delegate) const OVERRIDE; private: - virtual scoped_refptr<BlobData> LookupBlobData( + scoped_refptr<BlobData> LookupBlobData( net::URLRequest* request) const; - // No scoped_refptr because |blob_storage_controller_| is owned by the - // ProfileIOData, which also owns this ProtocolHandler. - BlobStorageController* const blob_storage_controller_; const scoped_refptr<fileapi::FileSystemContext> file_system_context_; const scoped_refptr<base::MessageLoopProxy> file_loop_proxy_; diff --git a/webkit/browser/blob/mock_blob_url_request_context.cc b/webkit/browser/blob/mock_blob_url_request_context.cc index 45c6134..7d14159 100644 --- a/webkit/browser/blob/mock_blob_url_request_context.cc +++ b/webkit/browser/blob/mock_blob_url_request_context.cc @@ -4,71 +4,45 @@ #include "webkit/browser/blob/mock_blob_url_request_context.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/blob/blob_url_request_job.h" +#include "webkit/browser/blob/blob_url_request_job_factory.h" #include "webkit/common/blob/blob_data.h" -namespace webkit_blob { - -namespace { - -class MockBlobProtocolHandler - : public net::URLRequestJobFactory::ProtocolHandler { - public: - explicit MockBlobProtocolHandler( - BlobStorageController* blob_storage_controller, - fileapi::FileSystemContext* file_system_context) - : blob_storage_controller_(blob_storage_controller), - file_system_context_(file_system_context) {} - - virtual ~MockBlobProtocolHandler() {} - - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE { - return new BlobURLRequestJob( - request, - network_delegate, - blob_storage_controller_->GetBlobDataFromUrl(request->url()), - file_system_context_, - base::MessageLoopProxy::current().get()); - } - - private: - webkit_blob::BlobStorageController* const blob_storage_controller_; - fileapi::FileSystemContext* const file_system_context_; - DISALLOW_COPY_AND_ASSIGN(MockBlobProtocolHandler); -}; - -} // namespace +namespace webkit_blob { MockBlobURLRequestContext::MockBlobURLRequestContext( fileapi::FileSystemContext* file_system_context) - : blob_storage_controller_(new BlobStorageController) { + : blob_storage_context_(new BlobStorageContext) { // Job factory owns the protocol handler. job_factory_.SetProtocolHandler( - "blob", new MockBlobProtocolHandler(blob_storage_controller_.get(), - file_system_context)); + "blob", new BlobProtocolHandler(file_system_context, + base::MessageLoopProxy::current())); set_job_factory(&job_factory_); } -MockBlobURLRequestContext::~MockBlobURLRequestContext() {} +MockBlobURLRequestContext::~MockBlobURLRequestContext() { +} ScopedTextBlob::ScopedTextBlob( const MockBlobURLRequestContext& request_context, - const GURL& blob_url, + const std::string& blob_id, const std::string& data) - : blob_url_(blob_url), - blob_storage_controller_(request_context.blob_storage_controller()) { - DCHECK(blob_storage_controller_); - scoped_refptr<BlobData> blob_data(new BlobData()); - blob_data->AppendData(data); - blob_storage_controller_->AddFinishedBlob(blob_url_, blob_data.get()); + : blob_id_(blob_id), + context_(request_context.blob_storage_context()) { + DCHECK(context_); + scoped_refptr<BlobData> blob_data(new BlobData(blob_id_)); + if (!data.empty()) + blob_data->AppendData(data); + handle_ = context_->AddFinishedBlob(blob_data); } ScopedTextBlob::~ScopedTextBlob() { - blob_storage_controller_->RemoveBlob(blob_url_); +} + +scoped_ptr<BlobDataHandle> ScopedTextBlob::GetBlobDataHandle() { + return context_->GetBlobDataFromUUID(blob_id_); } } // namespace webkit_blob diff --git a/webkit/browser/blob/mock_blob_url_request_context.h b/webkit/browser/blob/mock_blob_url_request_context.h index b89027c..a5d1acc 100644 --- a/webkit/browser/blob/mock_blob_url_request_context.h +++ b/webkit/browser/blob/mock_blob_url_request_context.h @@ -15,34 +15,40 @@ class FileSystemContext; namespace webkit_blob { -class BlobStorageController; +class BlobDataHandle; +class BlobStorageContext; class MockBlobURLRequestContext : public net::URLRequestContext { public: MockBlobURLRequestContext(fileapi::FileSystemContext* file_system_context); virtual ~MockBlobURLRequestContext(); - BlobStorageController* blob_storage_controller() const { - return blob_storage_controller_.get(); + BlobStorageContext* blob_storage_context() const { + return blob_storage_context_.get(); } private: net::URLRequestJobFactoryImpl job_factory_; - scoped_ptr<BlobStorageController> blob_storage_controller_; + scoped_ptr<BlobStorageContext> blob_storage_context_; DISALLOW_COPY_AND_ASSIGN(MockBlobURLRequestContext); }; class ScopedTextBlob { public: + // Registers a blob with the given |id| that contains |data|. ScopedTextBlob(const MockBlobURLRequestContext& request_context, - const GURL& blob_url, + const std::string& blob_id, const std::string& data); ~ScopedTextBlob(); + // Returns a BlobDataHandle referring to the scoped blob. + scoped_ptr<BlobDataHandle> GetBlobDataHandle(); + private: - const GURL blob_url_; - BlobStorageController* blob_storage_controller_; + const std::string blob_id_; + BlobStorageContext* context_; + scoped_ptr<BlobDataHandle> handle_; DISALLOW_COPY_AND_ASSIGN(ScopedTextBlob); }; diff --git a/webkit/browser/blob/view_blob_internals_job.cc b/webkit/browser/blob/view_blob_internals_job.cc index 41ef788..e0523a4 100644 --- a/webkit/browser/blob/view_blob_internals_job.cc +++ b/webkit/browser/blob/view_blob_internals_job.cc @@ -11,13 +11,14 @@ #include "base/i18n/time_formatting.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "net/base/escape.h" #include "net/base/net_errors.h" #include "net/url_request/url_request.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/common/blob/blob_data.h" namespace { @@ -34,6 +35,8 @@ const char kURL[] = "URL: "; const char kModificationTime[] = "Modification Time: "; const char kOffset[] = "Offset: "; const char kLength[] = "Length: "; +const char kUUID[] = "Uuid: "; +const char kRefcount[] = "Refcount: "; void StartHTML(std::string* out) { out->append( @@ -48,11 +51,11 @@ void StartHTML(std::string* out) { ".subsection_body { margin: 10px 0 10px 2em; }\n" ".subsection_title { font-weight: bold; }\n" "</style>\n" - "</head><body>\n"); + "</head><body>\n\n"); } void EndHTML(std::string* out) { - out->append("</body></html>"); + out->append("\n</body></html>"); } void AddHTMLBoldText(const std::string& text, std::string* out) { @@ -62,11 +65,11 @@ void AddHTMLBoldText(const std::string& text, std::string* out) { } void StartHTMLList(std::string* out) { - out->append("<ul>"); + out->append("\n<ul>"); } void EndHTMLList(std::string* out) { - out->append("</ul>"); + out->append("</ul>\n"); } void AddHTMLListItem(const std::string& element_title, @@ -76,21 +79,11 @@ void AddHTMLListItem(const std::string& element_title, // No need to escape element_title since constant string is passed. out->append(element_title); out->append(net::EscapeForHTML(element_data)); - out->append("</li>"); + out->append("</li>\n"); } -void AddHTMLButton(const std::string& title, - const std::string& command, - std::string* out) { - // No need to escape title since constant string is passed. - std::string escaped_command = net::EscapeForHTML(command.c_str()); - base::StringAppendF(out, - "<form action=\"\" method=\"GET\">\n" - "<input type=\"hidden\" name=\"remove\" value=\"%s\">\n" - "<input type=\"submit\" value=\"%s\">\n" - "</form><br/>\n", - escaped_command.c_str(), - title.c_str()); +void AddHorizontalRule(std::string* out) { + out->append("\n<hr>\n"); } } // namespace @@ -100,9 +93,9 @@ namespace webkit_blob { ViewBlobInternalsJob::ViewBlobInternalsJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, - BlobStorageController* blob_storage_controller) + BlobStorageContext* blob_storage_context) : net::URLRequestSimpleJob(request, network_delegate), - blob_storage_controller_(blob_storage_controller), + blob_storage_context_(blob_storage_context), weak_factory_(this) { } @@ -112,7 +105,7 @@ ViewBlobInternalsJob::~ViewBlobInternalsJob() { void ViewBlobInternalsJob::Start() { base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&ViewBlobInternalsJob::DoWorkAsync, + base::Bind(&ViewBlobInternalsJob::StartAsync, weak_factory_.GetWeakPtr())); } @@ -134,18 +127,6 @@ void ViewBlobInternalsJob::Kill() { weak_factory_.InvalidateWeakPtrs(); } -void ViewBlobInternalsJob::DoWorkAsync() { - if (request_->url().has_query() && - StartsWithASCII(request_->url().query(), "remove=", true)) { - std::string blob_url = request_->url().query().substr(strlen("remove=")); - blob_url = net::UnescapeURLComponent(blob_url, - net::UnescapeRule::NORMAL | net::UnescapeRule::URL_SPECIAL_CHARS); - blob_storage_controller_->RemoveBlob(GURL(blob_url)); - } - - StartAsync(); -} - int ViewBlobInternalsJob::GetData( std::string* mime_type, std::string* charset, @@ -156,7 +137,7 @@ int ViewBlobInternalsJob::GetData( data->clear(); StartHTML(data); - if (blob_storage_controller_->blob_map_.empty()) + if (blob_storage_context_->blob_map_.empty()) data->append(kEmptyBlobStorageMessage); else GenerateHTML(data); @@ -165,20 +146,47 @@ int ViewBlobInternalsJob::GetData( } void ViewBlobInternalsJob::GenerateHTML(std::string* out) const { - for (BlobStorageController::BlobMap::const_iterator iter = - blob_storage_controller_->blob_map_.begin(); - iter != blob_storage_controller_->blob_map_.end(); + for (BlobStorageContext::BlobMap::const_iterator iter = + blob_storage_context_->blob_map_.begin(); + iter != blob_storage_context_->blob_map_.end(); ++iter) { AddHTMLBoldText(iter->first, out); - AddHTMLButton(kRemove, iter->first, out); - GenerateHTMLForBlobData(*iter->second.get(), out); + GenerateHTMLForBlobData(*(iter->second.data.get()), + iter->second.refcount, + out); + } + if (!blob_storage_context_->public_blob_urls_.empty()) { + AddHorizontalRule(out); + for (BlobStorageContext::BlobURLMap::const_iterator iter = + blob_storage_context_->public_blob_urls_.begin(); + iter != blob_storage_context_->public_blob_urls_.end(); + ++iter) { + AddHTMLBoldText(iter->first.spec(), out); + StartHTMLList(out); + AddHTMLListItem(kUUID, iter->second, out); + EndHTMLList(out); + } + } + if (!blob_storage_context_->deprecated_blob_urls_.empty()) { + AddHorizontalRule(out); + for (BlobStorageContext::BlobURLMap::const_iterator iter = + blob_storage_context_->deprecated_blob_urls_.begin(); + iter != blob_storage_context_->deprecated_blob_urls_.end(); + ++iter) { + AddHTMLBoldText(iter->first.spec(), out); + StartHTMLList(out); + AddHTMLListItem(kUUID, iter->second, out); + EndHTMLList(out); + } } } void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data, + int refcount, std::string* out) { StartHTMLList(out); + AddHTMLListItem(kRefcount, base::IntToString(refcount), out); if (!blob_data.content_type().empty()) AddHTMLListItem(kContentType, blob_data.content_type(), out); if (!blob_data.content_disposition().empty()) @@ -213,12 +221,11 @@ void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data, } break; case BlobData::Item::TYPE_BLOB: - AddHTMLListItem(kType, "blob", out); - AddHTMLListItem(kURL, item.url().spec(), out); + NOTREACHED(); // Should be flattened in the storage context. break; case BlobData::Item::TYPE_FILE_FILESYSTEM: AddHTMLListItem(kType, "filesystem", out); - AddHTMLListItem(kURL, item.url().spec(), out); + AddHTMLListItem(kURL, item.filesystem_url().spec(), out); if (!item.expected_modification_time().is_null()) { AddHTMLListItem(kModificationTime, UTF16ToUTF8( TimeFormatFriendlyDateAndTime(item.expected_modification_time())), diff --git a/webkit/browser/blob/view_blob_internals_job.h b/webkit/browser/blob/view_blob_internals_job.h index 41687d9..ed9d657 100644 --- a/webkit/browser/blob/view_blob_internals_job.h +++ b/webkit/browser/blob/view_blob_internals_job.h @@ -18,7 +18,7 @@ class URLRequest; namespace webkit_blob { class BlobData; -class BlobStorageController; +class BlobStorageContext; // A job subclass that implements a protocol to inspect the internal // state of blob registry. @@ -27,7 +27,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ViewBlobInternalsJob public: ViewBlobInternalsJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - BlobStorageController* blob_storage_controller); + BlobStorageContext* blob_storage_context); virtual void Start() OVERRIDE; virtual int GetData(std::string* mime_type, @@ -41,12 +41,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ViewBlobInternalsJob private: virtual ~ViewBlobInternalsJob(); - void DoWorkAsync(); void GenerateHTML(std::string* out) const; static void GenerateHTMLForBlobData(const BlobData& blob_data, + int refcount, std::string* out); - BlobStorageController* blob_storage_controller_; + BlobStorageContext* blob_storage_context_; base::WeakPtrFactory<ViewBlobInternalsJob> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ViewBlobInternalsJob); diff --git a/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc b/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc index d8ecc28..1dfae25 100644 --- a/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc +++ b/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc @@ -15,7 +15,7 @@ #include "net/url_request/url_request_job_factory_impl.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/blob/blob_url_request_job.h" #include "webkit/browser/blob/mock_blob_url_request_context.h" #include "webkit/browser/fileapi/file_system_context.h" @@ -174,11 +174,12 @@ class FileSystemOperationImplWriteTest }; TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) { - const GURL blob_url("blob:success"); - ScopedTextBlob blob(url_request_context(), blob_url, "Hello, world!\n"); - + ScopedTextBlob blob(url_request_context(), + "blob-id:success", + "Hello, world!\n"); file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), blob_url, + &url_request_context(), URLForPath(virtual_path_), + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); @@ -190,19 +191,12 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) { } TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) { - GURL blob_url("blob:zero"); - scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData()); - - url_request_context().blob_storage_controller() - ->AddFinishedBlob(blob_url, blob_data.get()); - + ScopedTextBlob blob(url_request_context(), "blob_id:zero", ""); file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_path_), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); - url_request_context().blob_storage_controller()->RemoveBlob(blob_url); - EXPECT_EQ(0, bytes_written()); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(complete()); @@ -210,10 +204,12 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) { EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); } + TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) { + scoped_ptr<webkit_blob::BlobDataHandle> null_handle; file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_path_), - GURL("blob:invalid"), 0, RecordWriteCallback()); + null_handle.Pass(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(0, bytes_written()); @@ -224,14 +220,12 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) { } TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidFile) { - GURL blob_url("blob:writeinvalidfile"); - ScopedTextBlob blob(url_request_context(), blob_url, + ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile", "It\'ll not be written."); - file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(0, bytes_written()); @@ -248,13 +242,11 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) { true /* exclusive */, false /* recursive */, base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK)); - GURL blob_url("blob:writedir"); - ScopedTextBlob blob(url_request_context(), blob_url, + ScopedTextBlob blob(url_request_context(), "blob:writedir", "It\'ll not be written, too."); - file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_dir_path), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(0, bytes_written()); @@ -269,14 +261,13 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) { } TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) { - GURL blob_url("blob:success"); - ScopedTextBlob blob(url_request_context(), blob_url, "Hello, world!\n"); - + ScopedTextBlob blob(url_request_context(), "blob:success", + "Hello, world!\n"); quota_manager_->SetQuota( kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10); file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), blob_url, - 0, RecordWriteCallback()); + &url_request_context(), URLForPath(virtual_path_), + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(10, bytes_written()); @@ -287,13 +278,12 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) { } TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) { - GURL blob_url("blob:success"); - ScopedTextBlob blob(url_request_context(), blob_url, "Hello, world!\n"); - + ScopedTextBlob blob(url_request_context(), "blob:success", + "Hello, world!\n"); FileSystemOperationRunner::OperationID id = file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_path_), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback()); // We use RunAllPendings() instead of Run() here, because we won't dispatch // callbacks after Cancel() is issued (so no chance to Quit) nor do we need @@ -311,15 +301,13 @@ TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) { } TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelFailingWrite) { - GURL blob_url("blob:writeinvalidfile"); - ScopedTextBlob blob(url_request_context(), blob_url, + ScopedTextBlob blob(url_request_context(), "blob:writeinvalidfile", "It\'ll not be written."); - FileSystemOperationRunner::OperationID id = file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback()); // We use RunAllPendings() instead of Run() here, because we won't dispatch // callbacks after Cancel() is issued (so no chance to Quit) nor do we need diff --git a/webkit/browser/fileapi/file_system_operation_runner.cc b/webkit/browser/fileapi/file_system_operation_runner.cc index b899e1b..2c06aea 100644 --- a/webkit/browser/fileapi/file_system_operation_runner.cc +++ b/webkit/browser/fileapi/file_system_operation_runner.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "net/url_request/url_request_context.h" +#include "webkit/browser/blob/blob_url_request_job_factory.h" #include "webkit/browser/fileapi/file_observers.h" #include "webkit/browser/fileapi/file_stream_writer.h" #include "webkit/browser/fileapi/file_system_context.h" @@ -207,7 +208,7 @@ OperationID FileSystemOperationRunner::Remove( OperationID FileSystemOperationRunner::Write( const net::URLRequestContext* url_request_context, const FileSystemURL& url, - const GURL& blob_url, + scoped_ptr<webkit_blob::BlobDataHandle> blob, int64 offset, const WriteCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; @@ -226,11 +227,14 @@ OperationID FileSystemOperationRunner::Write( return kErrorOperationID; } - DCHECK(blob_url.is_valid()); scoped_ptr<FileWriterDelegate> writer_delegate( new FileWriterDelegate(writer.Pass())); - scoped_ptr<net::URLRequest> blob_request(url_request_context->CreateRequest( - blob_url, writer_delegate.get())); + + scoped_ptr<net::URLRequest> blob_request( + webkit_blob::BlobProtocolHandler::CreateBlobRequest( + blob.Pass(), + url_request_context, + writer_delegate.get())); OperationID id = operations_.Add(operation); PrepareForWrite(id, url); diff --git a/webkit/browser/fileapi/file_system_operation_runner.h b/webkit/browser/fileapi/file_system_operation_runner.h index 3b36c43..9543908 100644 --- a/webkit/browser/fileapi/file_system_operation_runner.h +++ b/webkit/browser/fileapi/file_system_operation_runner.h @@ -11,6 +11,7 @@ #include "base/id_map.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/webkit_storage_browser_export.h" @@ -97,10 +98,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner const StatusCallback& callback); // Writes contents of |blob_url| to |url| at |offset|. - // |url_request_context| is used to read contents in |blob_url|. + // |url_request_context| is used to read contents in |blob|. OperationID Write(const net::URLRequestContext* url_request_context, const FileSystemURL& url, - const GURL& blob_url, + scoped_ptr<webkit_blob::BlobDataHandle> blob, int64 offset, const WriteCallback& callback); diff --git a/webkit/child/weburlloader_impl.cc b/webkit/child/weburlloader_impl.cc index 63ce778..3a186a4 100644 --- a/webkit/child/weburlloader_impl.cc +++ b/webkit/child/weburlloader_impl.cc @@ -543,7 +543,7 @@ void WebURLLoaderImpl::Context::Start( break; } case WebHTTPBody::Element::TypeBlob: - request_body->AppendBlob(GURL(element.blobURL)); + request_body->AppendBlobDeprecated(GURL(element.blobURL)); break; default: NOTREACHED(); diff --git a/webkit/common/data_element.h b/webkit/common/data_element.h index 173d138..f93960b 100644 --- a/webkit/common/data_element.h +++ b/webkit/common/data_element.h @@ -48,13 +48,6 @@ class WEBKIT_COMMON_EXPORT DataElement { return expected_modification_time_; } - // TODO(michaeln): fixup callers to use filesytem_url() and blob_uuid(). - const GURL& url() const { - if (type_ == TYPE_FILE_FILESYSTEM) - return filesystem_url_; - return blob_url_; - } - // Sets TYPE_BYTES data. This copies the given data into the element. void SetToBytes(const char* bytes, int bytes_len) { type_ = TYPE_BYTES; diff --git a/webkit/common/resource_request_body.cc b/webkit/common/resource_request_body.cc index 6263529..097751b 100644 --- a/webkit/common/resource_request_body.cc +++ b/webkit/common/resource_request_body.cc @@ -26,11 +26,16 @@ void ResourceRequestBody::AppendFileRange( expected_modification_time); } -void ResourceRequestBody::AppendBlob(const GURL& blob_url) { +void ResourceRequestBody::AppendBlobDeprecated(const GURL& blob_url) { elements_.push_back(Element()); elements_.back().SetToBlobUrl(blob_url); } +void ResourceRequestBody::AppendBlob(const std::string& uuid) { + elements_.push_back(Element()); + elements_.back().SetToBlob(uuid); +} + void ResourceRequestBody::AppendFileSystemFileRange( const GURL& url, uint64 offset, uint64 length, const base::Time& expected_modification_time) { diff --git a/webkit/common/resource_request_body.h b/webkit/common/resource_request_body.h index c0bdc08..6f74e67 100644 --- a/webkit/common/resource_request_body.h +++ b/webkit/common/resource_request_body.h @@ -34,7 +34,8 @@ class WEBKIT_COMMON_EXPORT ResourceRequestBody void AppendFileRange(const base::FilePath& file_path, uint64 offset, uint64 length, const base::Time& expected_modification_time); - void AppendBlob(const GURL& blob_url); + void AppendBlobDeprecated(const GURL& blob_url); + void AppendBlob(const std::string& uuid); void AppendFileSystemFileRange(const GURL& url, uint64 offset, uint64 length, const base::Time& expected_modification_time); diff --git a/webkit/storage_browser.gyp b/webkit/storage_browser.gyp index 04d2565..9725e99 100644 --- a/webkit/storage_browser.gyp +++ b/webkit/storage_browser.gyp @@ -68,8 +68,6 @@ 'browser/blob/blob_data_handle.h', 'browser/blob/blob_storage_context.cc', 'browser/blob/blob_storage_context.h', - 'browser/blob/blob_storage_controller.cc', - 'browser/blob/blob_storage_controller.h', 'browser/blob/blob_storage_host.cc', 'browser/blob/blob_storage_host.h', 'browser/blob/blob_url_request_job.cc', |