Index: content/browser/fileapi/fileapi_message_filter.cc |
diff --git a/content/browser/fileapi/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc |
index 312e04dd4fd479c19c911cdf6cfa195e574d5308..be64cdf0632ca1d76c4d5e69d57c43af6ffaaf9c 100644 |
--- a/content/browser/fileapi/fileapi_message_filter.cc |
+++ b/content/browser/fileapi/fileapi_message_filter.cc |
@@ -12,15 +12,18 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/platform_file.h" |
#include "base/sequenced_task_runner.h" |
+#include "base/strings/string_util.h" |
#include "base/threading/thread.h" |
#include "base/time/time.h" |
#include "content/browser/child_process_security_policy_impl.h" |
#include "content/browser/fileapi/browser_file_system_helper.h" |
#include "content/browser/fileapi/chrome_blob_storage_context.h" |
+#include "content/browser/streams/stream_registry.h" |
#include "content/common/fileapi/file_system_messages.h" |
#include "content/common/fileapi/webblob_messages.h" |
#include "content/public/browser/user_metrics.h" |
#include "ipc/ipc_platform_file.h" |
+#include "net/base/io_buffer.h" |
#include "net/base/mime_util.h" |
#include "net/url_request/url_request_context.h" |
#include "net/url_request/url_request_context_getter.h" |
@@ -64,29 +67,35 @@ FileAPIMessageFilter::FileAPIMessageFilter( |
int process_id, |
net::URLRequestContextGetter* request_context_getter, |
fileapi::FileSystemContext* file_system_context, |
- ChromeBlobStorageContext* blob_storage_context) |
+ ChromeBlobStorageContext* blob_storage_context, |
+ StreamContext* stream_context) |
: process_id_(process_id), |
context_(file_system_context), |
request_context_getter_(request_context_getter), |
request_context_(NULL), |
- blob_storage_context_(blob_storage_context) { |
+ blob_storage_context_(blob_storage_context), |
+ stream_context_(stream_context) { |
DCHECK(context_); |
DCHECK(request_context_getter_.get()); |
DCHECK(blob_storage_context); |
+ DCHECK(stream_context); |
} |
FileAPIMessageFilter::FileAPIMessageFilter( |
int process_id, |
net::URLRequestContext* request_context, |
fileapi::FileSystemContext* file_system_context, |
- ChromeBlobStorageContext* blob_storage_context) |
+ ChromeBlobStorageContext* blob_storage_context, |
+ StreamContext* stream_context) |
: process_id_(process_id), |
context_(file_system_context), |
request_context_(request_context), |
- blob_storage_context_(blob_storage_context) { |
+ blob_storage_context_(blob_storage_context), |
+ stream_context_(stream_context) { |
DCHECK(context_); |
DCHECK(request_context_); |
DCHECK(blob_storage_context); |
+ DCHECK(stream_context); |
} |
void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) { |
@@ -100,6 +109,10 @@ void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) { |
} |
} |
+scoped_refptr<Stream> FileAPIMessageFilter::GetStreamForURL(const GURL& url) { |
+ return stream_context_->registry()->GetStream(url); |
+} |
kinuko
2013/07/23 13:57:23
nit: please match the method order in .cc and .h (
tyoshino (SeeGerritForStatus)
2013/07/24 12:14:20
Done.
|
+ |
void FileAPIMessageFilter::OnChannelClosing() { |
BrowserMessageFilter::OnChannelClosing(); |
@@ -107,7 +120,12 @@ void FileAPIMessageFilter::OnChannelClosing() { |
// 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)); |
+ const GURL url(*iter); |
+ // Intercept stream URLs. |
+ if (GetStreamForURL(url)) |
+ stream_context_->registry()->UnregisterStream(url); |
+ else |
+ blob_storage_context_->controller()->RemoveBlob(url); |
} |
in_transit_snapshot_files_.clear(); |
@@ -168,12 +186,16 @@ bool FileAPIMessageFilter::OnMessageReceived( |
IPC_MESSAGE_HANDLER(FileSystemHostMsg_SyncGetPlatformPath, |
OnSyncGetPlatformPath) |
IPC_MESSAGE_HANDLER(BlobHostMsg_StartBuildingBlob, OnStartBuildingBlob) |
- IPC_MESSAGE_HANDLER(BlobHostMsg_AppendBlobDataItem, OnAppendBlobDataItem) |
- IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemory, |
- OnAppendSharedMemory) |
+ IPC_MESSAGE_HANDLER(BlobHostMsg_StartBuildingStream, OnStartBuildingStream) |
+ IPC_MESSAGE_HANDLER(BlobHostMsg_AppendBlobDataItemToBlobOrStream, |
+ OnAppendBlobDataItemToBlobOrStream) |
+ IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemoryToBlobOrStream, |
+ OnAppendSharedMemoryToBlobOrStream) |
IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuildingBlob, OnFinishBuildingBlob) |
- IPC_MESSAGE_HANDLER(BlobHostMsg_CloneBlob, OnCloneBlob) |
- IPC_MESSAGE_HANDLER(BlobHostMsg_RemoveBlob, OnRemoveBlob) |
+ IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuildingStream, |
+ OnFinishBuildingStream) |
+ IPC_MESSAGE_HANDLER(BlobHostMsg_CloneBlobOrStream, OnCloneBlobOrStream) |
+ IPC_MESSAGE_HANDLER(BlobHostMsg_RemoveBlobOrStream, OnRemoveBlobOrStream) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP_EX() |
return handled; |
@@ -519,22 +541,53 @@ void FileAPIMessageFilter::OnStartBuildingBlob(const GURL& url) { |
blob_urls_.insert(url.spec()); |
} |
-void FileAPIMessageFilter::OnAppendBlobDataItem( |
+// Currently |content_type| is ignored inside Chromium. |
+// |
+// TODO(tyoshino): Set |content_type| to the stream. |
+void FileAPIMessageFilter::OnStartBuildingStream( |
+ const GURL& url, const std::string& content_type) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ // Only an internal Blob URL is expected here. See the BlobURL of the Blink. |
+ DCHECK(StartsWithASCII( |
Tom Sepez
2013/07/23 18:08:25
What happens if a compromised renderer violates th
tyoshino (SeeGerritForStatus)
2013/07/24 12:14:20
Done.
|
+ url.path(), "blobinternal%3A///", true /* case_sensitive*/)); |
kinuko
2013/07/23 13:57:23
nit: space between case_sensitive and '*/'
tyoshino (SeeGerritForStatus)
2013/07/24 12:14:20
Done.
|
+ // Use an empty security origin for now. Stream accepts a security origin |
+ // but how it's handled is not fixed yet. |
+ new Stream(stream_context_->registry(), |
+ NULL /* write_observer */, |
+ GURL() /* security_origin */, |
Tom Sepez
2013/07/23 18:08:25
Does this mean all streams share the same origin?
tyoshino (SeeGerritForStatus)
2013/07/24 12:14:20
Yes. But we have another origin checking system.
tyoshino (SeeGerritForStatus)
2013/07/29 07:44:00
Merged the fix.
|
+ url); |
+ blob_urls_.insert(url.spec()); |
+} |
+ |
+void FileAPIMessageFilter::OnAppendBlobDataItemToBlobOrStream( |
const GURL& url, const BlobData::Item& item) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ scoped_refptr<Stream> stream(GetStreamForURL(url)); |
+ if (stream.get()) { |
+ // Data for stream is delivered as TYPE_BYTES item. |
+ if (item.type() != BlobData::Item::TYPE_BYTES) { |
+ BadMessageReceived(); |
+ return; |
+ } |
+ stream->AddData(item.bytes(), item.length()); |
+ |
+ return; |
+ } |
+ |
if (item.type() == BlobData::Item::TYPE_FILE_FILESYSTEM) { |
base::PlatformFileError error; |
FileSystemURL filesystem_url(context_->CrackURL(item.url())); |
if (!HasPermissionsForFile(filesystem_url, |
fileapi::kReadFilePermissions, &error)) { |
- OnRemoveBlob(url); |
+ OnRemoveBlobOrStream(url); |
return; |
} |
} |
if (item.type() == BlobData::Item::TYPE_FILE && |
!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( |
process_id_, item.path())) { |
- OnRemoveBlob(url); |
+ OnRemoveBlobOrStream(url); |
return; |
} |
if (item.length() == 0) { |
@@ -544,7 +597,7 @@ void FileAPIMessageFilter::OnAppendBlobDataItem( |
blob_storage_context_->controller()->AppendBlobDataItem(url, item); |
} |
-void FileAPIMessageFilter::OnAppendSharedMemory( |
+void FileAPIMessageFilter::OnAppendSharedMemoryToBlobOrStream( |
const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size) { |
DCHECK(base::SharedMemory::IsHandleValid(handle)); |
Tom Sepez
2013/07/23 18:08:25
What happens if a compromised renderer either lies
tyoshino (SeeGerritForStatus)
2013/07/24 12:14:20
Filed a bug and CC-ed you.
|
if (!buffer_size) { |
@@ -557,7 +610,13 @@ void FileAPIMessageFilter::OnAppendSharedMemory( |
base::SharedMemory shared_memory(handle, true); |
#endif |
if (!shared_memory.Map(buffer_size)) { |
- OnRemoveBlob(url); |
+ OnRemoveBlobOrStream(url); |
+ return; |
+ } |
+ |
+ scoped_refptr<Stream> stream(GetStreamForURL(url)); |
+ if (stream.get()) { |
+ stream->AddData(static_cast<char*>(shared_memory.memory()), buffer_size); |
return; |
} |
@@ -573,16 +632,29 @@ void FileAPIMessageFilter::OnFinishBuildingBlob( |
blob_storage_context_->controller()->FinishBuildingBlob(url, content_type); |
} |
-void FileAPIMessageFilter::OnCloneBlob( |
+void FileAPIMessageFilter::OnFinishBuildingStream(const GURL& url) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ scoped_refptr<Stream> stream(GetStreamForURL(url)); |
+ if (stream.get()) |
+ stream->Finalize(); |
kinuko
2013/07/23 13:57:23
Should we DCHECK(stream.get()) here?
tyoshino (SeeGerritForStatus)
2013/07/24 12:14:20
Added NOTREACHED
|
+} |
+ |
+void FileAPIMessageFilter::OnCloneBlobOrStream( |
const GURL& url, const GURL& src_url) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- blob_storage_context_->controller()->CloneBlob(url, src_url); |
+ if (GetStreamForURL(src_url)) |
+ stream_context_->registry()->CloneStream(url, src_url); |
+ else |
+ blob_storage_context_->controller()->CloneBlob(url, src_url); |
blob_urls_.insert(url.spec()); |
} |
-void FileAPIMessageFilter::OnRemoveBlob(const GURL& url) { |
+void FileAPIMessageFilter::OnRemoveBlobOrStream(const GURL& url) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- blob_storage_context_->controller()->RemoveBlob(url); |
+ if (GetStreamForURL(url).get()) |
+ stream_context_->registry()->UnregisterStream(url); |
+ else |
+ blob_storage_context_->controller()->RemoveBlob(url); |
blob_urls_.erase(url.spec()); |
} |