summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authormichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 23:00:51 +0000
committermichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 23:00:51 +0000
commita3c71e8edf494687af2e67bc8fe8b013577bcbb6 (patch)
treeee46aaaf7a90f4b57065f6af59c2b6a647d92c00 /content
parent378429dc295cf26b11d20f9e52bc568e4dbf3b4e (diff)
downloadchromium_src-a3c71e8edf494687af2e67bc8fe8b013577bcbb6.zip
chromium_src-a3c71e8edf494687af2e67bc8fe8b013577bcbb6.tar.gz
chromium_src-a3c71e8edf494687af2e67bc8fe8b013577bcbb6.tar.bz2
A few improvements to Blob handling.
* Break large blobs into multiple ipcs during creation. * Use shared memory blocks for the xfer. * Rename some methods and IPCs for readability. * Cap memory usage in the browser process at 1G. BUG=97221 Review URL: http://codereview.chromium.org/7974011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105950 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/blob_message_filter.cc78
-rw-r--r--content/browser/renderer_host/blob_message_filter.h20
-rw-r--r--content/common/webblob_messages.h44
-rw-r--r--content/common/webblobregistry_impl.cc73
-rw-r--r--content/common/webblobregistry_impl.h14
-rw-r--r--content/common/webkit_param_traits.cc100
-rw-r--r--content/common/webkit_param_traits.h8
-rw-r--r--content/renderer/renderer_webkitplatformsupport_impl.cc6
8 files changed, 175 insertions, 168 deletions
diff --git a/content/browser/renderer_host/blob_message_filter.cc b/content/browser/renderer_host/blob_message_filter.cc
index 829c025..6c09451 100644
--- a/content/browser/renderer_host/blob_message_filter.cc
+++ b/content/browser/renderer_host/blob_message_filter.cc
@@ -11,6 +11,8 @@
#include "webkit/blob/blob_data.h"
#include "webkit/blob/blob_storage_controller.h"
+using webkit_blob::BlobData;
+
BlobMessageFilter::BlobMessageFilter(
int process_id,
ChromeBlobStorageContext* blob_storage_context)
@@ -28,7 +30,7 @@ void BlobMessageFilter::OnChannelClosing() {
// process.
for (base::hash_set<std::string>::const_iterator iter = blob_urls_.begin();
iter != blob_urls_.end(); ++iter) {
- blob_storage_context_->controller()->UnregisterBlobUrl(GURL(*iter));
+ blob_storage_context_->controller()->RemoveBlob(GURL(*iter));
}
}
@@ -38,48 +40,70 @@ bool BlobMessageFilter::OnMessageReceived(const IPC::Message& message,
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(BlobMessageFilter, message, *message_was_ok)
- IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterBlobUrl, OnRegisterBlobUrl)
- IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterBlobUrlFrom, OnRegisterBlobUrlFrom)
- IPC_MESSAGE_HANDLER(BlobHostMsg_UnregisterBlobUrl, OnUnregisterBlobUrl)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_StartBuildingBlob, OnStartBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_AppendBlobDataItem, OnAppendBlobDataItem)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemory,
+ OnAppendSharedMemory)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuildingBlob, OnFinishBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_CloneBlob, OnCloneBlob)
+ IPC_MESSAGE_HANDLER(BlobHostMsg_RemoveBlob, OnRemoveBlob)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-// Check if the child process has been granted permission to register the files.
-bool BlobMessageFilter::CheckPermission(
- webkit_blob::BlobData* blob_data) const {
- ChildProcessSecurityPolicy* policy =
- ChildProcessSecurityPolicy::GetInstance();
- for (std::vector<webkit_blob::BlobData::Item>::const_iterator iter =
- blob_data->items().begin();
- iter != blob_data->items().end(); ++iter) {
- if (iter->type() == webkit_blob::BlobData::TYPE_FILE) {
- if (!policy->CanReadFile(process_id_, iter->file_path()))
- return false;
- }
- }
- return true;
+void BlobMessageFilter::OnStartBuildingBlob(const GURL& url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ blob_storage_context_->controller()->StartBuildingBlob(url);
+ blob_urls_.insert(url.spec());
}
-void BlobMessageFilter::OnRegisterBlobUrl(
- const GURL& url, const scoped_refptr<webkit_blob::BlobData>& blob_data) {
+void BlobMessageFilter::OnAppendBlobDataItem(
+ const GURL& url, const BlobData::Item& item) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!CheckPermission(blob_data.get()))
+ if (item.type == BlobData::TYPE_FILE &&
+ !ChildProcessSecurityPolicy::GetInstance()->CanReadFile(
+ process_id_, item.file_path)) {
+ OnRemoveBlob(url);
return;
- blob_storage_context_->controller()->RegisterBlobUrl(url, blob_data);
- blob_urls_.insert(url.spec());
+ }
+ blob_storage_context_->controller()->AppendBlobDataItem(url, item);
+}
+
+void BlobMessageFilter::OnAppendSharedMemory(
+ const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size) {
+ DCHECK(base::SharedMemory::IsHandleValid(handle));
+#if defined(OS_WIN)
+ base::SharedMemory shared_memory(handle, true, peer_handle());
+#else
+ base::SharedMemory shared_memory(handle, true);
+#endif
+ if (!shared_memory.Map(buffer_size)) {
+ OnRemoveBlob(url);
+ return;
+ }
+
+ BlobData::Item item;
+ item.SetToDataExternal(static_cast<char*>(shared_memory.memory()),
+ buffer_size);
+ blob_storage_context_->controller()->AppendBlobDataItem(url, item);
+}
+
+void BlobMessageFilter::OnFinishBuildingBlob(
+ const GURL& url, const std::string& content_type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ blob_storage_context_->controller()->FinishBuildingBlob(url, content_type);
}
-void BlobMessageFilter::OnRegisterBlobUrlFrom(
+void BlobMessageFilter::OnCloneBlob(
const GURL& url, const GURL& src_url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_context_->controller()->RegisterBlobUrlFrom(url, src_url);
+ blob_storage_context_->controller()->CloneBlob(url, src_url);
blob_urls_.insert(url.spec());
}
-void BlobMessageFilter::OnUnregisterBlobUrl(const GURL& url) {
+void BlobMessageFilter::OnRemoveBlob(const GURL& url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_context_->controller()->UnregisterBlobUrl(url);
+ blob_storage_context_->controller()->RemoveBlob(url);
blob_urls_.erase(url.spec());
}
diff --git a/content/browser/renderer_host/blob_message_filter.h b/content/browser/renderer_host/blob_message_filter.h
index ace01db..24758ac 100644
--- a/content/browser/renderer_host/blob_message_filter.h
+++ b/content/browser/renderer_host/blob_message_filter.h
@@ -6,7 +6,9 @@
#define CONTENT_BROWSER_RENDERER_HOST_BLOB_MESSAGE_FILTER_H_
#include "base/hash_tables.h"
+#include "base/shared_memory.h"
#include "content/browser/browser_message_filter.h"
+#include "webkit/blob/blob_data.h"
class ChromeBlobStorageContext;
class GURL;
@@ -15,10 +17,6 @@ namespace IPC {
class Message;
}
-namespace webkit_blob {
-class BlobData;
-}
-
class BlobMessageFilter : public BrowserMessageFilter {
public:
BlobMessageFilter(int process_id,
@@ -31,12 +29,14 @@ class BlobMessageFilter : public BrowserMessageFilter {
bool* message_was_ok);
private:
- void OnRegisterBlobUrl(const GURL& url,
- const scoped_refptr<webkit_blob::BlobData>& blob_data);
- void OnRegisterBlobUrlFrom(const GURL& url, const GURL& src_url);
- void OnUnregisterBlobUrl(const GURL& url);
-
- bool CheckPermission(webkit_blob::BlobData* blob_data) const;
+ void OnStartBuildingBlob(const GURL& url);
+ void OnAppendBlobDataItem(const GURL& url,
+ const webkit_blob::BlobData::Item& item);
+ void OnAppendSharedMemory(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);
int process_id_;
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
diff --git a/content/common/webblob_messages.h b/content/common/webblob_messages.h
index 2cbb2b7..6fcd61f 100644
--- a/content/common/webblob_messages.h
+++ b/content/common/webblob_messages.h
@@ -11,19 +11,47 @@
#define IPC_MESSAGE_START BlobMsgStart
+IPC_ENUM_TRAITS(webkit_blob::BlobData::Type)
+
+IPC_STRUCT_TRAITS_BEGIN(webkit_blob::BlobData::Item)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(data)
+ IPC_STRUCT_TRAITS_MEMBER(file_path)
+ IPC_STRUCT_TRAITS_MEMBER(blob_url)
+ IPC_STRUCT_TRAITS_MEMBER(offset)
+ IPC_STRUCT_TRAITS_MEMBER(length)
+ IPC_STRUCT_TRAITS_MEMBER(expected_modification_time)
+IPC_STRUCT_TRAITS_END()
+
// Blob messages sent from the renderer to the browser.
-// Registers a blob URL referring to the specified blob data.
-IPC_MESSAGE_CONTROL2(BlobHostMsg_RegisterBlobUrl,
+
+// Registers a blob as being built.
+IPC_MESSAGE_CONTROL1(BlobHostMsg_StartBuildingBlob,
+ GURL /* url */)
+
+// Appends data to a blob being built.
+IPC_MESSAGE_CONTROL2(BlobHostMsg_AppendBlobDataItem,
+ GURL /* url */,
+ webkit_blob::BlobData::Item)
+
+// Appends data to a blob being built.
+IPC_SYNC_MESSAGE_CONTROL3_0(BlobHostMsg_SyncAppendSharedMemory,
+ GURL /* url */,
+ base::SharedMemoryHandle,
+ size_t /* buffer size */)
+
+// Finishes building a blob.
+IPC_MESSAGE_CONTROL2(BlobHostMsg_FinishBuildingBlob,
GURL /* url */,
- scoped_refptr<webkit_blob::BlobData> /* blob_data */)
+ std::string /* content_type */)
-// Registers a blob URL referring to the blob data identified by the specified
-// source URL.
-IPC_MESSAGE_CONTROL2(BlobHostMsg_RegisterBlobUrlFrom,
+// Creates a new blob that's a clone of an existing src blob.
+// The source blob must be fully built.
+IPC_MESSAGE_CONTROL2(BlobHostMsg_CloneBlob,
GURL /* url */,
GURL /* src_url */)
-// Unregister a blob URL.
-IPC_MESSAGE_CONTROL1(BlobHostMsg_UnregisterBlobUrl,
+// Removes a blob.
+IPC_MESSAGE_CONTROL1(BlobHostMsg_RemoveBlob,
GURL /* url */)
diff --git a/content/common/webblobregistry_impl.cc b/content/common/webblobregistry_impl.cc
index 7a6a1ea..53d7a74 100644
--- a/content/common/webblobregistry_impl.cc
+++ b/content/common/webblobregistry_impl.cc
@@ -5,18 +5,21 @@
#include "content/common/webblobregistry_impl.h"
#include "base/memory/ref_counted.h"
+#include "base/shared_memory.h"
+#include "content/common/child_thread.h"
#include "content/common/webblob_messages.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobData.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
#include "webkit/blob/blob_data.h"
+#include "webkit/glue/webkit_glue.h"
using WebKit::WebBlobData;
using WebKit::WebString;
using WebKit::WebURL;
-WebBlobRegistryImpl::WebBlobRegistryImpl(IPC::Message::Sender* sender)
- : sender_(sender) {
+WebBlobRegistryImpl::WebBlobRegistryImpl(ChildThread* child_thread)
+ : child_thread_(child_thread) {
}
WebBlobRegistryImpl::~WebBlobRegistryImpl() {
@@ -24,16 +27,72 @@ WebBlobRegistryImpl::~WebBlobRegistryImpl() {
void WebBlobRegistryImpl::registerBlobURL(
const WebURL& url, WebBlobData& data) {
- scoped_refptr<webkit_blob::BlobData> blob_data(
- new webkit_blob::BlobData(data));
- sender_->Send(new BlobHostMsg_RegisterBlobUrl(url, blob_data));
+ const size_t kLargeThresholdBytes = 250 * 1024;
+ const size_t kMaxSharedMemoryBytes = 10 * 1024 * 1024;
+
+ child_thread_->Send(new BlobHostMsg_StartBuildingBlob(url));
+ size_t i = 0;
+ WebBlobData::Item data_item;
+ while (data.itemAt(i++, data_item)) {
+ webkit_blob::BlobData::Item item;
+ switch (data_item.type) {
+ case WebBlobData::Item::TypeData: {
+ // WebBlobData does not allow partial data items.
+ DCHECK(!data_item.offset && data_item.length == -1);
+ if (data_item.data.size() < kLargeThresholdBytes) {
+ item.SetToData(data_item.data.data(), data_item.data.size());
+ child_thread_->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 data_size = data_item.data.size();
+ const char* data_ptr = data_item.data.data();
+ size_t shared_memory_size = std::min(
+ data_size, kMaxSharedMemoryBytes);
+ scoped_ptr<base::SharedMemory> shared_memory(
+ child_thread_->AllocateSharedMemory(shared_memory_size));
+ CHECK(shared_memory.get());
+ while (data_size) {
+ size_t chunk_size = std::min(data_size, shared_memory_size);
+ memcpy(shared_memory->memory(), data_ptr, chunk_size);
+ child_thread_->Send(new BlobHostMsg_SyncAppendSharedMemory(
+ url, shared_memory->handle(), chunk_size));
+ data_size -= chunk_size;
+ data_ptr += chunk_size;
+ }
+ }
+ break;
+ }
+ case WebBlobData::Item::TypeFile:
+ item.SetToFile(
+ webkit_glue::WebStringToFilePath(data_item.filePath),
+ static_cast<uint64>(data_item.offset),
+ static_cast<uint64>(data_item.length),
+ base::Time::FromDoubleT(data_item.expectedModificationTime));
+ child_thread_->Send(new BlobHostMsg_AppendBlobDataItem(url, item));
+ break;
+ case WebBlobData::Item::TypeBlob:
+ if (data_item.length) {
+ item.SetToBlob(
+ data_item.blobURL,
+ static_cast<uint64>(data_item.offset),
+ static_cast<uint64>(data_item.length));
+ }
+ child_thread_->Send(new BlobHostMsg_AppendBlobDataItem(url, item));
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+ child_thread_->Send(new BlobHostMsg_FinishBuildingBlob(
+ url, data.contentType().utf8().data()));
}
void WebBlobRegistryImpl::registerBlobURL(
const WebURL& url, const WebURL& src_url) {
- sender_->Send(new BlobHostMsg_RegisterBlobUrlFrom(url, src_url));
+ child_thread_->Send(new BlobHostMsg_CloneBlob(url, src_url));
}
void WebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) {
- sender_->Send(new BlobHostMsg_UnregisterBlobUrl(url));
+ child_thread_->Send(new BlobHostMsg_RemoveBlob(url));
}
diff --git a/content/common/webblobregistry_impl.h b/content/common/webblobregistry_impl.h
index 73395d9..6b05683 100644
--- a/content/common/webblobregistry_impl.h
+++ b/content/common/webblobregistry_impl.h
@@ -6,19 +6,23 @@
#define CHROME_COMMON_WEBBLOBREGISTRY_IMPL_H_
#pragma once
-#include "ipc/ipc_message.h"
+//#include "ipc/ipc_message.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobRegistry.h"
+class ChildThread;
+
+namespace base {
+class SharedMemory;
+}
+
namespace WebKit {
class WebBlobData;
-class WebBlobStorageData;
-class WebString;
class WebURL;
}
class WebBlobRegistryImpl : public WebKit::WebBlobRegistry {
public:
- explicit WebBlobRegistryImpl(IPC::Message::Sender* sender);
+ explicit WebBlobRegistryImpl(ChildThread* child_thread);
virtual ~WebBlobRegistryImpl();
// See WebBlobRegistry.h for documentation on these functions.
@@ -29,7 +33,7 @@ class WebBlobRegistryImpl : public WebKit::WebBlobRegistry {
virtual void unregisterBlobURL(const WebKit::WebURL& url);
private:
- IPC::Message::Sender* sender_;
+ ChildThread* child_thread_;
};
#endif // CHROME_COMMON_WEBBLOBREGISTRY_IMPL_H_
diff --git a/content/common/webkit_param_traits.cc b/content/common/webkit_param_traits.cc
index bed2f26..a10eaa8 100644
--- a/content/common/webkit_param_traits.cc
+++ b/content/common/webkit_param_traits.cc
@@ -150,106 +150,6 @@ void ParamTraits<scoped_refptr<webkit_glue::ResourceDevToolsInfo> >::Log(
l->append(")");
}
-// Only the webkit_blob::BlobData ParamTraits<> definition needs this
-// definition, so keep this in the implementation file so we can forward declare
-// BlobData in the header.
-template <>
-struct ParamTraits<webkit_blob::BlobData::Item> {
- typedef webkit_blob::BlobData::Item param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, static_cast<int>(p.type()));
- if (p.type() == webkit_blob::BlobData::TYPE_DATA) {
- WriteParam(m, p.data());
- } else if (p.type() == webkit_blob::BlobData::TYPE_FILE) {
- WriteParam(m, p.file_path());
- WriteParam(m, p.offset());
- WriteParam(m, p.length());
- WriteParam(m, p.expected_modification_time());
- } else {
- WriteParam(m, p.blob_url());
- WriteParam(m, p.offset());
- WriteParam(m, p.length());
- }
- }
- static bool Read(const Message* m, void** iter, param_type* r) {
- int type;
- if (!ReadParam(m, iter, &type))
- return false;
- if (type == webkit_blob::BlobData::TYPE_DATA) {
- std::string data;
- if (!ReadParam(m, iter, &data))
- return false;
- r->SetToData(data);
- } else if (type == webkit_blob::BlobData::TYPE_FILE) {
- FilePath file_path;
- uint64 offset, length;
- base::Time expected_modification_time;
- if (!ReadParam(m, iter, &file_path))
- return false;
- if (!ReadParam(m, iter, &offset))
- return false;
- if (!ReadParam(m, iter, &length))
- return false;
- if (!ReadParam(m, iter, &expected_modification_time))
- return false;
- r->SetToFile(file_path, offset, length, expected_modification_time);
- } else {
- DCHECK(type == webkit_blob::BlobData::TYPE_BLOB);
- GURL blob_url;
- uint64 offset, length;
- if (!ReadParam(m, iter, &blob_url))
- return false;
- if (!ReadParam(m, iter, &offset))
- return false;
- if (!ReadParam(m, iter, &length))
- return false;
- r->SetToBlob(blob_url, offset, length);
- }
- return true;
- }
- static void Log(const param_type& p, std::string* l) {
- l->append("<BlobData::Item>");
- }
-};
-
-void ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Write(
- Message* m, const param_type& p) {
- WriteParam(m, p.get() != NULL);
- if (p) {
- WriteParam(m, p->items());
- WriteParam(m, p->content_type());
- WriteParam(m, p->content_disposition());
- }
-}
-
-bool ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Read(
- const Message* m, void** iter, param_type* r) {
- bool has_object;
- if (!ReadParam(m, iter, &has_object))
- return false;
- if (!has_object)
- return true;
- std::vector<webkit_blob::BlobData::Item> items;
- if (!ReadParam(m, iter, &items))
- return false;
- std::string content_type;
- if (!ReadParam(m, iter, &content_type))
- return false;
- std::string content_disposition;
- if (!ReadParam(m, iter, &content_disposition))
- return false;
- *r = new webkit_blob::BlobData;
- (*r)->swap_items(&items);
- (*r)->set_content_type(content_type);
- (*r)->set_content_disposition(content_disposition);
- return true;
-}
-
-void ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Log(
- const param_type& p, std::string* l) {
- l->append("<webkit_blob::BlobData>");
-}
-
void ParamTraits<NPVariant_Param>::Write(Message* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.type));
if (p.type == NPVARIANT_PARAM_BOOL) {
diff --git a/content/common/webkit_param_traits.h b/content/common/webkit_param_traits.h
index 9808e59..8bf9973 100644
--- a/content/common/webkit_param_traits.h
+++ b/content/common/webkit_param_traits.h
@@ -90,14 +90,6 @@ struct ParamTraits<scoped_refptr<webkit_glue::ResourceDevToolsInfo> > {
};
template <>
-struct ParamTraits<scoped_refptr<webkit_blob::BlobData > > {
- typedef scoped_refptr<webkit_blob::BlobData> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, void** iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
struct ParamTraits<NPVariant_Param> {
typedef NPVariant_Param param_type;
static void Write(Message* m, const param_type& p);
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc
index 9c71370..6ed042b 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -604,9 +604,9 @@ RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
//------------------------------------------------------------------------------
WebBlobRegistry* RendererWebKitPlatformSupportImpl::blobRegistry() {
- // RenderThreadImpl::current can be NULL when running some tests.
- if (!blob_registry_.get() && RenderThreadImpl::current()) {
- blob_registry_.reset(new WebBlobRegistryImpl(RenderThreadImpl::Get()));
+ // ChildThread::current can be NULL when running some tests.
+ if (!blob_registry_.get() && ChildThread::current()) {
+ blob_registry_.reset(new WebBlobRegistryImpl(ChildThread::current()));
}
return blob_registry_.get();
}