Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: content/browser/blob_storage/blob_dispatcher_host.cc

Issue 2340133006: [WIP] Hack on Blob mojom (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/blob_storage/blob_dispatcher_host.h" 5 #include "content/browser/blob_storage/blob_dispatcher_host.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
(...skipping 29 matching lines...) Expand all
40 BDH_TRACING_ENUM_LAST 40 BDH_TRACING_ENUM_LAST
41 }; 41 };
42 42
43 } // namespace 43 } // namespace
44 44
45 BlobDispatcherHost::BlobDispatcherHost( 45 BlobDispatcherHost::BlobDispatcherHost(
46 int process_id, 46 int process_id,
47 scoped_refptr<ChromeBlobStorageContext> blob_storage_context, 47 scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
48 scoped_refptr<storage::FileSystemContext> file_system_context) 48 scoped_refptr<storage::FileSystemContext> file_system_context)
49 : BrowserMessageFilter(BlobMsgStart), 49 : BrowserMessageFilter(BlobMsgStart),
50 BrowserAssociatedInterface<mojom::BlobFactory>(this, this),
50 process_id_(process_id), 51 process_id_(process_id),
51 file_system_context_(std::move(file_system_context)), 52 file_system_context_(std::move(file_system_context)),
52 blob_storage_context_(std::move(blob_storage_context)) {} 53 blob_storage_context_(std::move(blob_storage_context)),
54 blob_bindings_(mojo::BindingSetDispatchMode::WITH_CONTEXT) {}
53 55
54 BlobDispatcherHost::~BlobDispatcherHost() { 56 BlobDispatcherHost::~BlobDispatcherHost() {
55 ClearHostFromBlobStorageContext(); 57 ClearHostFromBlobStorageContext();
56 } 58 }
57 59
58 void BlobDispatcherHost::OnChannelClosing() { 60 void BlobDispatcherHost::OnChannelClosing() {
59 ClearHostFromBlobStorageContext(); 61 ClearHostFromBlobStorageContext();
60 public_blob_urls_.clear(); 62 public_blob_urls_.clear();
61 blobs_inuse_map_.clear(); 63 blobs_inuse_map_.clear();
62 } 64 }
63 65
64 bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) { 66 bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) {
65 bool handled = true; 67 bool handled = true;
66 IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message) 68 IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message)
67 IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlobUUID, OnRegisterBlobUUID)
68 IPC_MESSAGE_HANDLER(BlobStorageMsg_StartBuildingBlob, OnStartBuildingBlob)
69 IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse) 69 IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse)
70 IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob)
71 IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount) 70 IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount)
72 IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount) 71 IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount)
73 IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL) 72 IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL)
74 IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL) 73 IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL)
75 IPC_MESSAGE_UNHANDLED(handled = false) 74 IPC_MESSAGE_UNHANDLED(handled = false)
76 IPC_END_MESSAGE_MAP() 75 IPC_END_MESSAGE_MAP()
77 return handled; 76 return handled;
78 } 77 }
79 78
80 void BlobDispatcherHost::OnRegisterBlobUUID( 79 void BlobDispatcherHost::BuildBlob(
81 const std::string& uuid, 80 const std::string& uuid,
82 const std::string& content_type, 81 const std::string& content_type,
83 const std::string& content_disposition, 82 const std::string& content_disposition,
84 const std::set<std::string>& referenced_blob_uuids) { 83 const std::vector<std::string>& referenced_blob_uuids,
84 const std::vector<storage::DataElement>& item_descriptions,
85 const BuildBlobCallback& callback) {
85 DCHECK_CURRENTLY_ON(BrowserThread::IO); 86 DCHECK_CURRENTLY_ON(BrowserThread::IO);
87
86 BlobStorageContext* context = this->context(); 88 BlobStorageContext* context = this->context();
87 if (uuid.empty() || context->registry().HasEntry(uuid) || 89 if (uuid.empty() || context->registry().HasEntry(uuid) ||
88 async_builder_.IsBeingBuilt(uuid)) { 90 async_builder_.IsBeingBuilt(uuid)) {
89 bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED); 91 bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED);
90 return; 92 return;
91 } 93 }
92 blobs_inuse_map_[uuid] = 1; 94 blobs_inuse_map_[uuid] = 1;
95 std::set<std::string> referenced_blob_uuid_set;
96 std::copy(referenced_blob_uuids.begin(), referenced_blob_uuids.end(),
97 std::inserter(referenced_blob_uuid_set,
98 referenced_blob_uuid_set.end()));
93 BlobTransportResult result = async_builder_.RegisterBlobUUID( 99 BlobTransportResult result = async_builder_.RegisterBlobUUID(
94 uuid, content_type, content_disposition, referenced_blob_uuids, context); 100 uuid, content_type, content_disposition, referenced_blob_uuid_set,
101 context);
95 switch (result) { 102 switch (result) {
96 case BlobTransportResult::BAD_IPC: 103 case BlobTransportResult::BAD_IPC:
97 blobs_inuse_map_.erase(uuid); 104 blobs_inuse_map_.erase(uuid);
98 bad_message::ReceivedBadMessage(this, 105 bad_message::ReceivedBadMessage(this,
99 bad_message::BDH_CONSTRUCTION_FAILED); 106 bad_message::BDH_CONSTRUCTION_FAILED);
100 break; 107 break;
101 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN: 108 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
102 // The async builder builds the blob as broken, and we just need to send 109 // The async builder builds the blob as broken, and we just need to send
103 // the cancel message back to the renderer. 110 // the cancel message back to the renderer.
104 Send(new BlobStorageMsg_CancelBuildingBlob( 111 callback.Run(
105 uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN)); 112 nullptr, mojom::BlobCreationCancelCode::REFERENCED_BLOB_BROKEN);
106 break; 113 return;
107 case BlobTransportResult::DONE: 114 case BlobTransportResult::DONE:
108 break; 115 break;
109 case BlobTransportResult::CANCEL_MEMORY_FULL: 116 case BlobTransportResult::CANCEL_MEMORY_FULL:
110 case BlobTransportResult::CANCEL_FILE_ERROR: 117 case BlobTransportResult::CANCEL_FILE_ERROR:
111 case BlobTransportResult::CANCEL_UNKNOWN: 118 case BlobTransportResult::CANCEL_UNKNOWN:
112 case BlobTransportResult::PENDING_RESPONSES: 119 case BlobTransportResult::PENDING_RESPONSES:
113 NOTREACHED(); 120 NOTREACHED();
114 break; 121 break;
115 } 122 }
116 }
117 123
118 void BlobDispatcherHost::OnStartBuildingBlob(
119 const std::string& uuid,
120 const std::vector<storage::DataElement>& descriptions) {
121 DCHECK_CURRENTLY_ON(BrowserThread::IO);
122 if (uuid.empty()) { 124 if (uuid.empty()) {
123 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 125 SendIPCResponse(callback, BlobTransportResult::BAD_IPC);
124 return; 126 return;
125 } 127 }
126 BlobStorageContext* context = this->context(); 128 BlobStorageContext* context = this->context();
127 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid); 129 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
128 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) { 130 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
129 // We ignore messages for blobs that don't exist to handle the case where 131 // We ignore messages for blobs that don't exist to handle the case where
130 // the renderer de-refs a blob that we're still constructing, and there are 132 // the renderer de-refs a blob that we're still constructing, and there are
131 // no references to that blob. We ignore broken as well, in the case where 133 // no references to that blob. We ignore broken as well, in the case where
132 // we decided to break a blob after RegisterBlobUUID is called. 134 // we decided to break a blob after RegisterBlobUUID is called.
133 // Second, if the last dereference of the blob happened on a different host, 135 // Second, if the last dereference of the blob happened on a different host,
134 // then we still haven't gotten rid of the 'building' state in the original 136 // then we still haven't gotten rid of the 'building' state in the original
135 // host. So we call cancel, and send the message just in case that happens. 137 // host. So we call cancel, and send the message just in case that happens.
136 if (async_builder_.IsBeingBuilt(uuid)) { 138 if (async_builder_.IsBeingBuilt(uuid)) {
137 async_builder_.CancelBuildingBlob( 139 async_builder_.CancelBuildingBlob(
138 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, 140 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
139 context); 141 context);
140 Send(new BlobStorageMsg_CancelBuildingBlob( 142 callback.Run(
141 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING)); 143 nullptr,
144 mojom::BlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
142 } 145 }
143 return; 146 return;
144 } 147 }
145 if (!async_builder_.IsBeingBuilt(uuid)) { 148 if (!async_builder_.IsBeingBuilt(uuid)) {
146 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 149 SendIPCResponse(callback, BlobTransportResult::BAD_IPC);
147 return; 150 return;
148 } 151 }
149 152
150 ChildProcessSecurityPolicyImpl* security_policy = 153 ChildProcessSecurityPolicyImpl* security_policy =
151 ChildProcessSecurityPolicyImpl::GetInstance(); 154 ChildProcessSecurityPolicyImpl::GetInstance();
152 for (const DataElement& item : descriptions) { 155 for (const DataElement& item : descriptions) {
153 if (item.type() == storage::DataElement::TYPE_FILE_FILESYSTEM) { 156 if (item.type() == storage::DataElement::TYPE_FILE_FILESYSTEM) {
154 FileSystemURL filesystem_url( 157 FileSystemURL filesystem_url(
155 file_system_context_->CrackURL(item.filesystem_url())); 158 file_system_context_->CrackURL(item.filesystem_url()));
156 if (!FileSystemURLIsValid(file_system_context_.get(), filesystem_url) || 159 if (!FileSystemURLIsValid(file_system_context_.get(), filesystem_url) ||
157 !security_policy->CanReadFileSystemFile(process_id_, 160 !security_policy->CanReadFileSystemFile(process_id_,
158 filesystem_url)) { 161 filesystem_url)) {
159 async_builder_.CancelBuildingBlob( 162 async_builder_.CancelBuildingBlob(
160 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context); 163 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context);
161 Send(new BlobStorageMsg_CancelBuildingBlob( 164 callback.Run(nullptr, mojom::BlobCreationCancelCode::FILE_WRITE_FAILED);
162 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
163 return; 165 return;
164 } 166 }
165 } 167 }
166 if (item.type() == storage::DataElement::TYPE_FILE && 168 if (item.type() == storage::DataElement::TYPE_FILE &&
167 !security_policy->CanReadFile(process_id_, item.path())) { 169 !security_policy->CanReadFile(process_id_, item.path())) {
168 async_builder_.CancelBuildingBlob( 170 async_builder_.CancelBuildingBlob(
169 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context); 171 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context);
170 Send(new BlobStorageMsg_CancelBuildingBlob( 172 callback.Run(nullptr, mojom::BlobCreationCancelCode::FILE_WRITE_FAILED);
171 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
172 return; 173 return;
173 } 174 }
174 } 175 }
175 176
176 // |this| owns async_builder_ so using base::Unretained(this) is safe. 177 // |this| owns async_builder_ so using base::Unretained(this) is safe.
177 BlobTransportResult result = async_builder_.StartBuildingBlob( 178 BlobTransportResult result = async_builder_.StartBuildingBlob(
178 uuid, descriptions, context->memory_available(), context, 179 uuid, descriptions, context->memory_available(), context,
179 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this), 180 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
180 uuid)); 181 uuid));
181 SendIPCResponse(uuid, result); 182 SendIPCResponse(callback, result);
182 } 183 }
183 184
184 void BlobDispatcherHost::OnMemoryItemResponse( 185 void BlobDispatcherHost::OnMemoryItemResponse(
185 const std::string& uuid, 186 const std::string& uuid,
186 const std::vector<storage::BlobItemBytesResponse>& responses) { 187 const std::vector<storage::BlobItemBytesResponse>& responses) {
187 DCHECK_CURRENTLY_ON(BrowserThread::IO); 188 DCHECK_CURRENTLY_ON(BrowserThread::IO);
188 if (uuid.empty()) { 189 if (uuid.empty()) {
189 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 190 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
190 return; 191 return;
191 } 192 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles, 346 std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles,
346 std::unique_ptr<std::vector<base::File>> files) { 347 std::unique_ptr<std::vector<base::File>> files) {
347 DCHECK_CURRENTLY_ON(BrowserThread::IO); 348 DCHECK_CURRENTLY_ON(BrowserThread::IO);
348 std::vector<IPC::PlatformFileForTransit> file_handles; 349 std::vector<IPC::PlatformFileForTransit> file_handles;
349 // TODO(dmurph): Support file-backed blob transportation. 350 // TODO(dmurph): Support file-backed blob transportation.
350 DCHECK(files->empty()); 351 DCHECK(files->empty());
351 Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles, 352 Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles,
352 file_handles)); 353 file_handles));
353 } 354 }
354 355
355 void BlobDispatcherHost::SendIPCResponse(const std::string& uuid, 356 void BlobDispatcherHost::SendIPCResponse(const BuildBlobCallback& callback,
356 storage::BlobTransportResult result) { 357 storage::BlobTransportResult result) {
358 mojom::BlobAssociatedPtr new_blob;
359 mojom::BlobCreationCancelCode cancel_code =
360 mojom:BlobCreationCancelCode::UNKNOWN;
357 switch (result) { 361 switch (result) {
358 case BlobTransportResult::BAD_IPC: 362 case BlobTransportResult::BAD_IPC:
359 bad_message::ReceivedBadMessage(this, 363 bad_message::ReceivedBadMessage(this,
360 bad_message::BDH_CONSTRUCTION_FAILED); 364 bad_message::BDH_CONSTRUCTION_FAILED);
361 return; 365 cancel_code = mojom::BlobCreationCancelCode::UNKNOWN;
366 break;
362 case BlobTransportResult::CANCEL_MEMORY_FULL: 367 case BlobTransportResult::CANCEL_MEMORY_FULL:
363 Send(new BlobStorageMsg_CancelBuildingBlob( 368 cancel_code = mojom::BlobCreationCancelCode::OUT_OF_MEMORY;
364 uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY)); 369 break;
365 return;
366 case BlobTransportResult::CANCEL_FILE_ERROR: 370 case BlobTransportResult::CANCEL_FILE_ERROR:
367 Send(new BlobStorageMsg_CancelBuildingBlob( 371 cancel_code = mojom::BlobCreationCancelCode::FILE_WRITE_FAILED;
368 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED)); 372 break;
369 return;
370 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN: 373 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
371 Send(new BlobStorageMsg_CancelBuildingBlob( 374 cancel_code = mojom::BlobCreationCancelCode::REFERENCED_BLOB_BROKEN;
372 uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN)); 375 break;
373 return;
374 case BlobTransportResult::CANCEL_UNKNOWN: 376 case BlobTransportResult::CANCEL_UNKNOWN:
375 Send(new BlobStorageMsg_CancelBuildingBlob( 377 cancel_code = mojom::BlobCreationCancelCode::UNKNOWN;
376 uuid, IPCBlobCreationCancelCode::UNKNOWN)); 378 break;
377 return;
378 case BlobTransportResult::PENDING_RESPONSES: 379 case BlobTransportResult::PENDING_RESPONSES:
379 return; 380 return;
380 case BlobTransportResult::DONE: 381 case BlobTransportResult::DONE:
381 Send(new BlobStorageMsg_DoneBuildingBlob(uuid)); 382 new_blob = blob_bindings_.CreateInterfacePtrAndBind(this);
382 return; 383 break;
384 default:
385 NOTREACHED();
386 break;
383 } 387 }
384 NOTREACHED(); 388
389 callback.Run(std::move(new_blob), cancel_code);
385 } 390 }
386 391
387 bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) { 392 bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) {
388 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end(); 393 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
389 } 394 }
390 395
391 bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) { 396 bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) {
392 return public_blob_urls_.find(blob_url) != public_blob_urls_.end(); 397 return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
393 } 398 }
394 399
395 void BlobDispatcherHost::ClearHostFromBlobStorageContext() { 400 void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
396 BlobStorageContext* context = this->context(); 401 BlobStorageContext* context = this->context();
397 for (const auto& url : public_blob_urls_) { 402 for (const auto& url : public_blob_urls_) {
398 context->RevokePublicBlobURL(url); 403 context->RevokePublicBlobURL(url);
399 } 404 }
400 for (const auto& uuid_refnum_pair : blobs_inuse_map_) { 405 for (const auto& uuid_refnum_pair : blobs_inuse_map_) {
401 for (int i = 0; i < uuid_refnum_pair.second; ++i) 406 for (int i = 0; i < uuid_refnum_pair.second; ++i)
402 context->DecrementBlobRefCount(uuid_refnum_pair.first); 407 context->DecrementBlobRefCount(uuid_refnum_pair.first);
403 } 408 }
404 async_builder_.CancelAll(context); 409 async_builder_.CancelAll(context);
405 } 410 }
406 411
407 } // namespace content 412 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/blob_storage/blob_dispatcher_host.h ('k') | content/child/blob_storage/blob_message_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698