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

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

Issue 1853333003: [BlobAsync] Faster shortcuttin, make renderer controller leaky & alive. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Disabling fast shutdown when transfering blobs Created 4 years, 8 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 "content/browser/bad_message.h" 10 #include "content/browser/bad_message.h"
11 #include "content/browser/fileapi/chrome_blob_storage_context.h" 11 #include "content/browser/fileapi/chrome_blob_storage_context.h"
12 #include "content/common/fileapi/webblob_messages.h" 12 #include "content/common/fileapi/webblob_messages.h"
13 #include "ipc/ipc_platform_file.h" 13 #include "ipc/ipc_platform_file.h"
14 #include "storage/browser/blob/blob_storage_context.h" 14 #include "storage/browser/blob/blob_storage_context.h"
15 #include "storage/browser/blob/blob_transport_result.h" 15 #include "storage/browser/blob/blob_transport_result.h"
16 #include "storage/common/blob_storage/blob_item_bytes_request.h" 16 #include "storage/common/blob_storage/blob_item_bytes_request.h"
17 #include "storage/common/blob_storage/blob_item_bytes_response.h" 17 #include "storage/common/blob_storage/blob_item_bytes_response.h"
18 #include "storage/common/data_element.h" 18 #include "storage/common/data_element.h"
19 #include "url/gurl.h" 19 #include "url/gurl.h"
20 20
21 using storage::BlobStorageContext; 21 using storage::BlobStorageContext;
22 using storage::BlobStorageRegistry; 22 using storage::BlobStorageRegistry;
23 using storage::BlobTransportResult; 23 using storage::BlobTransportResult;
24 using storage::IPCBlobCreationCancelCode; 24 using storage::IPCBlobCreationCancelCode;
25 25
26 namespace content { 26 namespace content {
27 27
28 BlobDispatcherHost::BlobDispatcherHost( 28 BlobDispatcherHost::BlobDispatcherHost(
29 ChromeBlobStorageContext* blob_storage_context) 29 ChromeBlobStorageContext* blob_storage_context,
30 SetSuddenTerminationAllowedCallback set_sudden_termination_allowed)
30 : BrowserMessageFilter(BlobMsgStart), 31 : BrowserMessageFilter(BlobMsgStart),
32 set_sudden_termination_allowed_(set_sudden_termination_allowed),
31 blob_storage_context_(blob_storage_context) {} 33 blob_storage_context_(blob_storage_context) {}
32 34
33 BlobDispatcherHost::~BlobDispatcherHost() { 35 BlobDispatcherHost::~BlobDispatcherHost() {
34 ClearHostFromBlobStorageContext(); 36 ClearHostFromBlobStorageContext();
35 } 37 }
36 38
37 void BlobDispatcherHost::OnChannelClosing() { 39 void BlobDispatcherHost::OnChannelClosing() {
38 ClearHostFromBlobStorageContext(); 40 ClearHostFromBlobStorageContext();
39 public_blob_urls_.clear(); 41 public_blob_urls_.clear();
40 blobs_inuse_map_.clear(); 42 blobs_inuse_map_.clear();
(...skipping 27 matching lines...) Expand all
68 return; 70 return;
69 } 71 }
70 blobs_inuse_map_[uuid] = 1; 72 blobs_inuse_map_[uuid] = 1;
71 BlobTransportResult result = async_builder_.RegisterBlobUUID( 73 BlobTransportResult result = async_builder_.RegisterBlobUUID(
72 uuid, content_type, content_disposition, referenced_blob_uuids, context); 74 uuid, content_type, content_disposition, referenced_blob_uuids, context);
73 switch (result) { 75 switch (result) {
74 case BlobTransportResult::BAD_IPC: 76 case BlobTransportResult::BAD_IPC:
75 blobs_inuse_map_.erase(uuid); 77 blobs_inuse_map_.erase(uuid);
76 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_OPERATION); 78 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_OPERATION);
77 break; 79 break;
78 ;
79 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN: 80 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
80 // The async builder builds the blob as broken, and we just need to send 81 // The async builder builds the blob as broken, and we just need to send
81 // the cancel message back to the renderer. 82 // the cancel message back to the renderer.
82 Send(new BlobStorageMsg_CancelBuildingBlob( 83 Send(new BlobStorageMsg_CancelBuildingBlob(
83 uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN)); 84 uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
84 break; 85 break;
85 case BlobTransportResult::DONE: 86 case BlobTransportResult::DONE:
87 // This means the builder used to be empty, and we're successfully
88 // building
89 // the blob.
90 if (async_builder_.blob_building_count() == 1) {
91 set_sudden_termination_allowed_.Run(false);
92 }
86 break; 93 break;
87 case BlobTransportResult::CANCEL_MEMORY_FULL: 94 case BlobTransportResult::CANCEL_MEMORY_FULL:
88 case BlobTransportResult::CANCEL_FILE_ERROR: 95 case BlobTransportResult::CANCEL_FILE_ERROR:
89 case BlobTransportResult::CANCEL_UNKNOWN: 96 case BlobTransportResult::CANCEL_UNKNOWN:
90 case BlobTransportResult::PENDING_RESPONSES: 97 case BlobTransportResult::PENDING_RESPONSES:
91 NOTREACHED(); 98 NOTREACHED();
92 break; 99 break;
93 } 100 }
94 } 101 }
95 102
(...skipping 14 matching lines...) Expand all
110 // we decided to break a blob after RegisterBlobUUID is called. 117 // we decided to break a blob after RegisterBlobUUID is called.
111 // Second, if the last dereference of the blob happened on a different host, 118 // Second, if the last dereference of the blob happened on a different host,
112 // then we still haven't gotten rid of the 'building' state in the original 119 // then we still haven't gotten rid of the 'building' state in the original
113 // host. So we call cancel, and send the message just in case that happens. 120 // host. So we call cancel, and send the message just in case that happens.
114 if (async_builder_.IsBeingBuilt(uuid)) { 121 if (async_builder_.IsBeingBuilt(uuid)) {
115 async_builder_.CancelBuildingBlob( 122 async_builder_.CancelBuildingBlob(
116 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, 123 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
117 context); 124 context);
118 Send(new BlobStorageMsg_CancelBuildingBlob( 125 Send(new BlobStorageMsg_CancelBuildingBlob(
119 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING)); 126 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
127 AllowSuddenTerminationIfBuilderEmpty();
120 } 128 }
121 return; 129 return;
122 } 130 }
123 if (!async_builder_.IsBeingBuilt(uuid)) { 131 if (!async_builder_.IsBeingBuilt(uuid)) {
124 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 132 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
125 return; 133 return;
126 } 134 }
127 // |this| owns async_builder_ so using base::Unretained(this) is safe. 135 // |this| owns async_builder_ so using base::Unretained(this) is safe.
128 BlobTransportResult result = async_builder_.StartBuildingBlob( 136 BlobTransportResult result = async_builder_.StartBuildingBlob(
129 uuid, descriptions, context->memory_available(), context, 137 uuid, descriptions, context->memory_available(), context,
130 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this), 138 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
131 uuid)); 139 uuid));
132 SendIPCResponse(uuid, result); 140 SendIPCResponse(uuid, result);
141 if (result != BlobTransportResult::PENDING_RESPONSES) {
142 AllowSuddenTerminationIfBuilderEmpty();
143 }
133 } 144 }
134 145
135 void BlobDispatcherHost::OnMemoryItemResponse( 146 void BlobDispatcherHost::OnMemoryItemResponse(
136 const std::string& uuid, 147 const std::string& uuid,
137 const std::vector<storage::BlobItemBytesResponse>& responses) { 148 const std::vector<storage::BlobItemBytesResponse>& responses) {
138 DCHECK_CURRENTLY_ON(BrowserThread::IO); 149 DCHECK_CURRENTLY_ON(BrowserThread::IO);
139 if (uuid.empty()) { 150 if (uuid.empty()) {
140 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 151 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
141 return; 152 return;
142 } 153 }
143 BlobStorageContext* context = this->context(); 154 BlobStorageContext* context = this->context();
144 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid); 155 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
145 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) { 156 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
146 // We ignore messages for blobs that don't exist to handle the case where 157 // We ignore messages for blobs that don't exist to handle the case where
147 // the renderer de-refs a blob that we're still constructing, and there are 158 // the renderer de-refs a blob that we're still constructing, and there are
148 // no references to that blob. We ignore broken as well, in the case where 159 // no references to that blob. We ignore broken as well, in the case where
149 // we decided to break a blob after sending the memory request. 160 // we decided to break a blob after sending the memory request.
150 // Note: if a blob is broken, then it can't be in the async_builder.
151 // Second, if the last dereference of the blob happened on a different host, 161 // Second, if the last dereference of the blob happened on a different host,
152 // then we still haven't gotten rid of the 'building' state in the original 162 // then we still haven't gotten rid of the 'building' state in the original
153 // host. So we call cancel, and send the message just in case that happens. 163 // host. So we call cancel, and send the message just in case that happens.
154 if (async_builder_.IsBeingBuilt(uuid)) { 164 if (async_builder_.IsBeingBuilt(uuid)) {
155 async_builder_.CancelBuildingBlob( 165 async_builder_.CancelBuildingBlob(
156 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, 166 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
157 context); 167 context);
158 Send(new BlobStorageMsg_CancelBuildingBlob( 168 Send(new BlobStorageMsg_CancelBuildingBlob(
159 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING)); 169 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
170 AllowSuddenTerminationIfBuilderEmpty();
160 } 171 }
161 return; 172 return;
162 } 173 }
163 if (!async_builder_.IsBeingBuilt(uuid)) { 174 if (!async_builder_.IsBeingBuilt(uuid)) {
164 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 175 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
165 return; 176 return;
166 } 177 }
167 BlobTransportResult result = 178 BlobTransportResult result =
168 async_builder_.OnMemoryResponses(uuid, responses, context); 179 async_builder_.OnMemoryResponses(uuid, responses, context);
169 SendIPCResponse(uuid, result); 180 SendIPCResponse(uuid, result);
181 if (result != BlobTransportResult::PENDING_RESPONSES) {
182 AllowSuddenTerminationIfBuilderEmpty();
183 }
170 } 184 }
171 185
172 void BlobDispatcherHost::OnCancelBuildingBlob( 186 void BlobDispatcherHost::OnCancelBuildingBlob(
173 const std::string& uuid, 187 const std::string& uuid,
174 const storage::IPCBlobCreationCancelCode code) { 188 const storage::IPCBlobCreationCancelCode code) {
175 DCHECK_CURRENTLY_ON(BrowserThread::IO); 189 DCHECK_CURRENTLY_ON(BrowserThread::IO);
176 if (uuid.empty()) { 190 if (uuid.empty()) {
177 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 191 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
178 return; 192 return;
179 } 193 }
180 BlobStorageContext* context = this->context(); 194 BlobStorageContext* context = this->context();
181 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid); 195 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
182 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) { 196 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
183 // We ignore messages for blobs that don't exist to handle the case where 197 // We ignore messages for blobs that don't exist to handle the case where
184 // the renderer de-refs a blob that we're still constructing, and there are 198 // the renderer de-refs a blob that we're still constructing, and there are
185 // no references to that blob. We ignore broken as well, in the case where 199 // no references to that blob. We ignore broken as well, in the case where
186 // we decided to break a blob and the renderer also decided to cancel. 200 // we decided to break a blob and the renderer also decided to cancel.
187 // Note: if a blob is broken, then it can't be in the async_builder.
188 // Second, if the last dereference of the blob happened on a different host, 201 // Second, if the last dereference of the blob happened on a different host,
189 // then we still haven't gotten rid of the 'building' state in the original 202 // then we still haven't gotten rid of the 'building' state in the original
190 // host. So we call cancel just in case this happens. 203 // host. So we call cancel just in case this happens.
191 async_builder_.CancelBuildingBlob( 204 if (async_builder_.IsBeingBuilt(uuid)) {
192 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, 205 async_builder_.CancelBuildingBlob(
193 context); 206 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
207 context);
208 AllowSuddenTerminationIfBuilderEmpty();
209 }
194 return; 210 return;
195 } 211 }
196 if (!async_builder_.IsBeingBuilt(uuid)) { 212 if (!async_builder_.IsBeingBuilt(uuid)) {
197 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); 213 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
198 return; 214 return;
199 } 215 }
200 VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. " 216 VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. "
201 << " Reason: " << static_cast<int>(code) << "."; 217 << " Reason: " << static_cast<int>(code) << ".";
202 async_builder_.CancelBuildingBlob(uuid, code, context); 218 async_builder_.CancelBuildingBlob(uuid, code, context);
219 AllowSuddenTerminationIfBuilderEmpty();
203 } 220 }
204 221
205 void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) { 222 void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
206 DCHECK_CURRENTLY_ON(BrowserThread::IO); 223 DCHECK_CURRENTLY_ON(BrowserThread::IO);
207 BlobStorageContext* context = this->context(); 224 BlobStorageContext* context = this->context();
208 if (uuid.empty() || !context->registry().HasEntry(uuid)) { 225 if (uuid.empty() || !context->registry().HasEntry(uuid)) {
209 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_OPERATION); 226 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_OPERATION);
210 return; 227 return;
211 } 228 }
212 context->IncrementBlobRefCount(uuid); 229 context->IncrementBlobRefCount(uuid);
(...skipping 14 matching lines...) Expand all
227 // If the blob has been deleted in the context and we're still building it, 244 // If the blob has been deleted in the context and we're still building it,
228 // this means we have no references waiting to read it. Clear the building 245 // this means we have no references waiting to read it. Clear the building
229 // state and send a cancel message to the renderer. 246 // state and send a cancel message to the renderer.
230 if (async_builder_.IsBeingBuilt(uuid) && 247 if (async_builder_.IsBeingBuilt(uuid) &&
231 !context->registry().HasEntry(uuid)) { 248 !context->registry().HasEntry(uuid)) {
232 async_builder_.CancelBuildingBlob( 249 async_builder_.CancelBuildingBlob(
233 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, 250 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
234 context); 251 context);
235 Send(new BlobStorageMsg_CancelBuildingBlob( 252 Send(new BlobStorageMsg_CancelBuildingBlob(
236 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING)); 253 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
254 AllowSuddenTerminationIfBuilderEmpty();
237 } 255 }
238 } 256 }
239 } 257 }
240 258
241 void BlobDispatcherHost::OnRegisterPublicBlobURL(const GURL& public_url, 259 void BlobDispatcherHost::OnRegisterPublicBlobURL(const GURL& public_url,
242 const std::string& uuid) { 260 const std::string& uuid) {
243 DCHECK_CURRENTLY_ON(BrowserThread::IO); 261 DCHECK_CURRENTLY_ON(BrowserThread::IO);
244 BlobStorageContext* context = this->context(); 262 BlobStorageContext* context = this->context();
245 if (uuid.empty() || !IsInUseInHost(uuid) || 263 if (uuid.empty() || !IsInUseInHost(uuid) ||
246 context->registry().IsURLMapped(public_url)) { 264 context->registry().IsURLMapped(public_url)) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 338
321 void BlobDispatcherHost::ClearHostFromBlobStorageContext() { 339 void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
322 BlobStorageContext* context = this->context(); 340 BlobStorageContext* context = this->context();
323 for (const auto& url : public_blob_urls_) { 341 for (const auto& url : public_blob_urls_) {
324 context->RevokePublicBlobURL(url); 342 context->RevokePublicBlobURL(url);
325 } 343 }
326 for (const auto& uuid_refnum_pair : blobs_inuse_map_) { 344 for (const auto& uuid_refnum_pair : blobs_inuse_map_) {
327 for (int i = 0; i < uuid_refnum_pair.second; ++i) 345 for (int i = 0; i < uuid_refnum_pair.second; ++i)
328 context->DecrementBlobRefCount(uuid_refnum_pair.first); 346 context->DecrementBlobRefCount(uuid_refnum_pair.first);
329 } 347 }
330 async_builder_.CancelAll(context); 348 if (!async_builder_.IsEmpty()) {
349 async_builder_.CancelAll(context);
350 set_sudden_termination_allowed_.Run(true);
351 }
352 }
353
354 void BlobDispatcherHost::AllowSuddenTerminationIfBuilderEmpty() {
355 if (async_builder_.IsEmpty()) {
356 set_sudden_termination_allowed_.Run(true);
357 }
331 } 358 }
332 359
333 } // namespace content 360 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698