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

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

Issue 2055053003: [BlobAsync] Disk support for blob storage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixes, working w/ Layout tests Created 4 years, 5 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"
11 #include "content/browser/bad_message.h" 11 #include "content/browser/bad_message.h"
12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" 12 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
13 #include "content/common/fileapi/webblob_messages.h" 13 #include "content/common/fileapi/webblob_messages.h"
14 #include "ipc/ipc_platform_file.h" 14 #include "ipc/ipc_platform_file.h"
15 #include "storage/browser/blob/blob_data_handle.h"
15 #include "storage/browser/blob/blob_storage_context.h" 16 #include "storage/browser/blob/blob_storage_context.h"
16 #include "storage/browser/blob/blob_transport_result.h" 17 #include "storage/browser/blob/blob_transport_result.h"
17 #include "storage/common/blob_storage/blob_item_bytes_request.h" 18 #include "storage/common/blob_storage/blob_item_bytes_request.h"
18 #include "storage/common/blob_storage/blob_item_bytes_response.h" 19 #include "storage/common/blob_storage/blob_item_bytes_response.h"
19 #include "storage/common/data_element.h" 20 #include "storage/common/data_element.h"
20 #include "url/gurl.h" 21 #include "url/gurl.h"
21 22
22 using storage::BlobStorageContext; 23 using storage::BlobStorageContext;
23 using storage::BlobStorageRegistry; 24 using storage::BlobStorageRegistry;
24 using storage::BlobTransportResult; 25 using storage::BlobTransportResult;
(...skipping 22 matching lines...) Expand all
47 48
48 void BlobDispatcherHost::OnChannelClosing() { 49 void BlobDispatcherHost::OnChannelClosing() {
49 ClearHostFromBlobStorageContext(); 50 ClearHostFromBlobStorageContext();
50 public_blob_urls_.clear(); 51 public_blob_urls_.clear();
51 blobs_inuse_map_.clear(); 52 blobs_inuse_map_.clear();
52 } 53 }
53 54
54 bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) { 55 bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) {
55 bool handled = true; 56 bool handled = true;
56 IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message) 57 IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message)
57 IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlobUUID, OnRegisterBlobUUID) 58 IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlob, OnRegisterBlob)
58 IPC_MESSAGE_HANDLER(BlobStorageMsg_StartBuildingBlob, OnStartBuildingBlob)
59 IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse) 59 IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse)
60 IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob) 60 IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob)
61 IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount) 61 IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount)
62 IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount) 62 IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount)
63 IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL) 63 IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL)
64 IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL) 64 IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL)
65 IPC_MESSAGE_UNHANDLED(handled = false) 65 IPC_MESSAGE_UNHANDLED(handled = false)
66 IPC_END_MESSAGE_MAP() 66 IPC_END_MESSAGE_MAP()
67 return handled; 67 return handled;
68 } 68 }
69 69
70 void BlobDispatcherHost::OnRegisterBlobUUID( 70 void BlobDispatcherHost::OnRegisterBlob(
71 const std::string& uuid, 71 const std::string& uuid,
72 const std::string& content_type, 72 const std::string& content_type,
73 const std::string& content_disposition, 73 const std::string& content_disposition,
74 const std::set<std::string>& referenced_blob_uuids) { 74 const std::vector<storage::DataElement>& descriptions) {
75 DCHECK_CURRENTLY_ON(BrowserThread::IO); 75 DCHECK_CURRENTLY_ON(BrowserThread::IO);
76 BlobStorageContext* context = this->context(); 76 BlobStorageContext* context = this->context();
77 if (uuid.empty() || context->registry().HasEntry(uuid) || 77 if (uuid.empty() || context->registry().HasEntry(uuid) ||
78 async_builder_.IsBeingBuilt(uuid)) { 78 async_builder_.IsBeingBuilt(uuid)) {
79 bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED); 79 bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED);
80 return; 80 return;
81 } 81 }
82 blobs_inuse_map_[uuid] = 1; 82 blobs_inuse_map_[uuid] = 1;
83 BlobTransportResult result = async_builder_.RegisterBlobUUID( 83 std::unique_ptr<storage::BlobDataHandle> handle;
michaeln 2016/07/07 20:05:20 This local variable isn't used in any obvious way,
84 uuid, content_type, content_disposition, referenced_blob_uuids, context); 84 BlobTransportResult result = async_builder_.RegisterBlob(
85 switch (result) { 85 uuid, content_type, content_disposition, descriptions, context, &handle,
86 case BlobTransportResult::BAD_IPC: 86 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
87 blobs_inuse_map_.erase(uuid); 87 uuid),
88 bad_message::ReceivedBadMessage(this, 88 base::Bind(&BlobDispatcherHost::CancelBlob, base::Unretained(this), uuid),
89 bad_message::BDH_CONSTRUCTION_FAILED); 89 base::Bind(&BlobDispatcherHost::SendIPCResponse, base::Unretained(this),
90 break; 90 uuid, BlobTransportResult::DONE));
91 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN: 91 if (result == BlobTransportResult::BAD_IPC) {
92 // The async builder builds the blob as broken, and we just need to send 92 blobs_inuse_map_.erase(uuid);
michaeln 2016/07/07 20:05:20 you can probably get rid of some branching logic h
93 // the cancel message back to the renderer. 93 } else {
94 Send(new BlobStorageMsg_CancelBuildingBlob( 94 context->IncrementBlobRefCount(uuid);
michaeln 2016/07/07 20:05:20 Where is the balancing call to Decrement? Oh, this
95 uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
96 break;
97 case BlobTransportResult::DONE:
98 break;
99 case BlobTransportResult::CANCEL_MEMORY_FULL:
100 case BlobTransportResult::CANCEL_FILE_ERROR:
101 case BlobTransportResult::CANCEL_UNKNOWN:
102 case BlobTransportResult::PENDING_RESPONSES:
103 NOTREACHED();
104 break;
105 } 95 }
106 }
107
108 void BlobDispatcherHost::OnStartBuildingBlob(
109 const std::string& uuid,
110 const std::vector<storage::DataElement>& descriptions) {
111 DCHECK_CURRENTLY_ON(BrowserThread::IO);
112 if (uuid.empty()) {
113 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
114 return;
115 }
116 BlobStorageContext* context = this->context();
117 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
118 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
119 // We ignore messages for blobs that don't exist to handle the case where
120 // the renderer de-refs a blob that we're still constructing, and there are
121 // no references to that blob. We ignore broken as well, in the case where
122 // we decided to break a blob after RegisterBlobUUID is called.
123 // Second, if the last dereference of the blob happened on a different host,
124 // then we still haven't gotten rid of the 'building' state in the original
125 // host. So we call cancel, and send the message just in case that happens.
126 if (async_builder_.IsBeingBuilt(uuid)) {
127 async_builder_.CancelBuildingBlob(
128 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
129 context);
130 Send(new BlobStorageMsg_CancelBuildingBlob(
131 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
132 }
133 return;
134 }
135 if (!async_builder_.IsBeingBuilt(uuid)) {
136 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
137 return;
138 }
139 // |this| owns async_builder_ so using base::Unretained(this) is safe.
140 BlobTransportResult result = async_builder_.StartBuildingBlob(
141 uuid, descriptions, context->memory_available(), context,
142 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
143 uuid));
144 SendIPCResponse(uuid, result); 96 SendIPCResponse(uuid, result);
145 } 97 }
146 98
147 void BlobDispatcherHost::OnMemoryItemResponse( 99 void BlobDispatcherHost::OnMemoryItemResponse(
148 const std::string& uuid, 100 const std::string& uuid,
149 const std::vector<storage::BlobItemBytesResponse>& responses) { 101 const std::vector<storage::BlobItemBytesResponse>& responses) {
150 DCHECK_CURRENTLY_ON(BrowserThread::IO); 102 DCHECK_CURRENTLY_ON(BrowserThread::IO);
151 if (uuid.empty()) { 103 if (uuid.empty()) {
152 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 104 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
153 return; 105 return;
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 return blob_storage_context_->context(); 254 return blob_storage_context_->context();
303 } 255 }
304 256
305 void BlobDispatcherHost::SendMemoryRequest( 257 void BlobDispatcherHost::SendMemoryRequest(
306 const std::string& uuid, 258 const std::string& uuid,
307 std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests, 259 std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
308 std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles, 260 std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles,
309 std::unique_ptr<std::vector<base::File>> files) { 261 std::unique_ptr<std::vector<base::File>> files) {
310 DCHECK_CURRENTLY_ON(BrowserThread::IO); 262 DCHECK_CURRENTLY_ON(BrowserThread::IO);
311 std::vector<IPC::PlatformFileForTransit> file_handles; 263 std::vector<IPC::PlatformFileForTransit> file_handles;
312 // TODO(dmurph): Support file-backed blob transportation. 264 for (base::File& file : *files) {
313 DCHECK(files->empty()); 265 file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file)));
266 }
314 Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles, 267 Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles,
315 file_handles)); 268 file_handles));
316 } 269 }
317 270
318 void BlobDispatcherHost::SendIPCResponse(const std::string& uuid, 271 void BlobDispatcherHost::SendIPCResponse(const std::string& uuid,
319 storage::BlobTransportResult result) { 272 storage::BlobTransportResult result) {
320 switch (result) { 273 switch (result) {
321 case BlobTransportResult::BAD_IPC: 274 case BlobTransportResult::BAD_IPC:
322 bad_message::ReceivedBadMessage(this, 275 bad_message::ReceivedBadMessage(this,
323 bad_message::BDH_CONSTRUCTION_FAILED); 276 bad_message::BDH_CONSTRUCTION_FAILED);
(...skipping 16 matching lines...) Expand all
340 return; 293 return;
341 case BlobTransportResult::PENDING_RESPONSES: 294 case BlobTransportResult::PENDING_RESPONSES:
342 return; 295 return;
343 case BlobTransportResult::DONE: 296 case BlobTransportResult::DONE:
344 Send(new BlobStorageMsg_DoneBuildingBlob(uuid)); 297 Send(new BlobStorageMsg_DoneBuildingBlob(uuid));
345 return; 298 return;
346 } 299 }
347 NOTREACHED(); 300 NOTREACHED();
348 } 301 }
349 302
303 void BlobDispatcherHost::CancelBlob(const std::string& uuid,
michaeln 2016/07/07 20:05:20 maybe name this SendCancelBlob in keeping with how
304 IPCBlobCreationCancelCode reason) {
305 Send(new BlobStorageMsg_CancelBuildingBlob(uuid, reason));
306 }
307
350 bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) { 308 bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) {
351 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end(); 309 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
352 } 310 }
353 311
354 bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) { 312 bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) {
355 return public_blob_urls_.find(blob_url) != public_blob_urls_.end(); 313 return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
356 } 314 }
357 315
358 void BlobDispatcherHost::ClearHostFromBlobStorageContext() { 316 void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
359 BlobStorageContext* context = this->context(); 317 BlobStorageContext* context = this->context();
360 for (const auto& url : public_blob_urls_) { 318 for (const auto& url : public_blob_urls_) {
361 context->RevokePublicBlobURL(url); 319 context->RevokePublicBlobURL(url);
362 } 320 }
363 for (const auto& uuid_refnum_pair : blobs_inuse_map_) { 321 for (const auto& uuid_refnum_pair : blobs_inuse_map_) {
364 for (int i = 0; i < uuid_refnum_pair.second; ++i) 322 for (int i = 0; i < uuid_refnum_pair.second; ++i)
365 context->DecrementBlobRefCount(uuid_refnum_pair.first); 323 context->DecrementBlobRefCount(uuid_refnum_pair.first);
366 } 324 }
367 async_builder_.CancelAll(context); 325 async_builder_.CancelAll(context);
368 } 326 }
369 327
370 } // namespace content 328 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698