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

Side by Side Diff: Source/modules/indexeddb/IDBRequest.cpp

Issue 235933013: Add the backchannel for Blobs to be received into Blink from the database backend. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rolled in feedback Created 6 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 21 matching lines...) Expand all
32 #include "bindings/v8/ExceptionState.h" 32 #include "bindings/v8/ExceptionState.h"
33 #include "bindings/v8/ExceptionStatePlaceholder.h" 33 #include "bindings/v8/ExceptionStatePlaceholder.h"
34 #include "bindings/v8/IDBBindingUtilities.h" 34 #include "bindings/v8/IDBBindingUtilities.h"
35 #include "core/dom/ExecutionContext.h" 35 #include "core/dom/ExecutionContext.h"
36 #include "core/events/EventQueue.h" 36 #include "core/events/EventQueue.h"
37 #include "modules/indexeddb/IDBCursorWithValue.h" 37 #include "modules/indexeddb/IDBCursorWithValue.h"
38 #include "modules/indexeddb/IDBDatabase.h" 38 #include "modules/indexeddb/IDBDatabase.h"
39 #include "modules/indexeddb/IDBEventDispatcher.h" 39 #include "modules/indexeddb/IDBEventDispatcher.h"
40 #include "modules/indexeddb/IDBTracing.h" 40 #include "modules/indexeddb/IDBTracing.h"
41 #include "platform/SharedBuffer.h" 41 #include "platform/SharedBuffer.h"
42 #include "public/platform/WebBlobInfo.h"
42 43
43 using blink::WebIDBCursor; 44 using blink::WebIDBCursor;
44 45
45 namespace WebCore { 46 namespace WebCore {
46 47
47 PassRefPtr<IDBRequest> IDBRequest::create(ExecutionContext* context, PassRefPtr< IDBAny> source, IDBTransaction* transaction) 48 PassRefPtr<IDBRequest> IDBRequest::create(ExecutionContext* context, PassRefPtr< IDBAny> source, IDBTransaction* transaction)
48 { 49 {
49 RefPtr<IDBRequest> request(adoptRef(new IDBRequest(context, source, transact ion))); 50 RefPtr<IDBRequest> request(adoptRef(new IDBRequest(context, source, transact ion)));
50 request->suspendIfNeeded(); 51 request->suspendIfNeeded();
51 // Requests associated with IDBFactory (open/deleteDatabase/getDatabaseNames ) are not associated with transactions. 52 // Requests associated with IDBFactory (open/deleteDatabase/getDatabaseNames ) are not associated with transactions.
(...skipping 17 matching lines...) Expand all
69 , m_didFireUpgradeNeededEvent(false) 70 , m_didFireUpgradeNeededEvent(false)
70 , m_preventPropagation(false) 71 , m_preventPropagation(false)
71 , m_resultDirty(true) 72 , m_resultDirty(true)
72 { 73 {
73 ScriptWrappable::init(this); 74 ScriptWrappable::init(this);
74 } 75 }
75 76
76 IDBRequest::~IDBRequest() 77 IDBRequest::~IDBRequest()
77 { 78 {
78 ASSERT(m_readyState == DONE || m_readyState == EarlyDeath || !executionConte xt()); 79 ASSERT(m_readyState == DONE || m_readyState == EarlyDeath || !executionConte xt());
80 handleBlobAcks();
79 } 81 }
80 82
81 ScriptValue IDBRequest::result(ExceptionState& exceptionState) 83 ScriptValue IDBRequest::result(ExceptionState& exceptionState)
82 { 84 {
83 if (m_readyState != DONE) { 85 if (m_readyState != DONE) {
84 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::request NotFinishedErrorMessage); 86 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::request NotFinishedErrorMessage);
85 return ScriptValue(); 87 return ScriptValue();
86 } 88 }
87 if (m_contextStopped || !executionContext()) 89 if (m_contextStopped || !executionContext())
88 return ScriptValue(); 90 return ScriptValue();
89 m_resultDirty = false; 91 m_resultDirty = false;
90 return idbAnyToScriptValue(m_scriptState.get(), m_result); 92 ScriptValue value = idbAnyToScriptValue(m_scriptState.get(), m_result);
93 handleBlobAcks();
94 return value;
91 } 95 }
92 96
93 PassRefPtrWillBeRawPtr<DOMError> IDBRequest::error(ExceptionState& exceptionStat e) const 97 PassRefPtrWillBeRawPtr<DOMError> IDBRequest::error(ExceptionState& exceptionStat e) const
94 { 98 {
95 if (m_readyState != DONE) { 99 if (m_readyState != DONE) {
96 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::request NotFinishedErrorMessage); 100 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::request NotFinishedErrorMessage);
97 return nullptr; 101 return nullptr;
98 } 102 }
99 return m_error; 103 return m_error;
100 } 104 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 { 176 {
173 if (!m_result) 177 if (!m_result)
174 return 0; 178 return 0;
175 if (m_result->type() == IDBAny::IDBCursorType) 179 if (m_result->type() == IDBAny::IDBCursorType)
176 return m_result->idbCursor(); 180 return m_result->idbCursor();
177 if (m_result->type() == IDBAny::IDBCursorWithValueType) 181 if (m_result->type() == IDBAny::IDBCursorWithValueType)
178 return m_result->idbCursorWithValue(); 182 return m_result->idbCursorWithValue();
179 return 0; 183 return 0;
180 } 184 }
181 185
182 void IDBRequest::setResultCursor(PassRefPtr<IDBCursor> cursor, PassRefPtr<IDBKey > key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value) 186 void IDBRequest::setResultCursor(PassRefPtr<IDBCursor> cursor, PassRefPtr<IDBKey > key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr <Vector<blink::WebBlobInfo> > blobInfo)
183 { 187 {
184 ASSERT(m_readyState == PENDING); 188 ASSERT(m_readyState == PENDING);
185 m_cursorKey = key; 189 m_cursorKey = key;
186 m_cursorPrimaryKey = primaryKey; 190 m_cursorPrimaryKey = primaryKey;
187 m_cursorValue = value; 191 m_cursorValue = value;
192 ASSERT(!m_blobInfo.get());
193 m_blobInfo = blobInfo;
188 194
189 onSuccessInternal(IDBAny::create(cursor)); 195 onSuccessInternal(IDBAny::create(cursor));
190 } 196 }
191 197
192 void IDBRequest::checkForReferenceCycle() 198 void IDBRequest::checkForReferenceCycle()
193 { 199 {
194 // If this request and its cursor have the only references 200 // If this request and its cursor have the only references
195 // to each other, then explicitly break the cycle. 201 // to each other, then explicitly break the cycle.
196 IDBCursor* cursor = getResultCursor(); 202 IDBCursor* cursor = getResultCursor();
197 if (!cursor || cursor->request() != this) 203 if (!cursor || cursor->request() != this)
198 return; 204 return;
199 205
200 if (!hasOneRef() || !cursor->hasOneRef()) 206 if (!hasOneRef() || !cursor->hasOneRef())
201 return; 207 return;
202 208
203 m_result.clear(); 209 m_result.clear();
204 } 210 }
205 211
212 void IDBRequest::handleBlobAcks()
213 {
214 if (m_blobInfo.get() && m_blobInfo->size()) {
215 m_transaction->db()->ackReceivedBlobs(m_blobInfo.get());
216 m_blobInfo.clear();
217 }
218 }
219
206 bool IDBRequest::shouldEnqueueEvent() const 220 bool IDBRequest::shouldEnqueueEvent() const
207 { 221 {
208 if (m_contextStopped || !executionContext()) 222 if (m_contextStopped || !executionContext())
209 return false; 223 return false;
210 ASSERT(m_readyState == PENDING || m_readyState == DONE); 224 ASSERT(m_readyState == PENDING || m_readyState == DONE);
211 if (m_requestAborted) 225 if (m_requestAborted)
212 return false; 226 return false;
213 ASSERT(m_readyState == PENDING); 227 ASSERT(m_readyState == PENDING);
214 ASSERT(!m_error && !m_result); 228 ASSERT(!m_error && !m_result);
215 return true; 229 return true;
(...skipping 15 matching lines...) Expand all
231 IDB_TRACE("IDBRequest::onSuccess(StringList)"); 245 IDB_TRACE("IDBRequest::onSuccess(StringList)");
232 if (!shouldEnqueueEvent()) 246 if (!shouldEnqueueEvent())
233 return; 247 return;
234 248
235 RefPtr<DOMStringList> domStringList = DOMStringList::create(); 249 RefPtr<DOMStringList> domStringList = DOMStringList::create();
236 for (size_t i = 0; i < stringList.size(); ++i) 250 for (size_t i = 0; i < stringList.size(); ++i)
237 domStringList->append(stringList[i]); 251 domStringList->append(stringList[i]);
238 onSuccessInternal(IDBAny::create(domStringList.release())); 252 onSuccessInternal(IDBAny::create(domStringList.release()));
239 } 253 }
240 254
241 void IDBRequest::onSuccess(PassOwnPtr<blink::WebIDBCursor> backend, PassRefPtr<I DBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value) 255 void IDBRequest::onSuccess(PassOwnPtr<blink::WebIDBCursor> backend, PassRefPtr<I DBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value, PassO wnPtr<Vector<blink::WebBlobInfo> > blobInfo)
242 { 256 {
243 IDB_TRACE("IDBRequest::onSuccess(IDBCursor)"); 257 IDB_TRACE("IDBRequest::onSuccess(IDBCursor)");
244 if (!shouldEnqueueEvent()) 258 if (!shouldEnqueueEvent())
245 return; 259 return;
246 260
247 ASSERT(!m_pendingCursor); 261 ASSERT(!m_pendingCursor);
248 RefPtr<IDBCursor> cursor; 262 RefPtr<IDBCursor> cursor;
249 switch (m_cursorType) { 263 switch (m_cursorType) {
250 case IndexedDB::CursorKeyOnly: 264 case IndexedDB::CursorKeyOnly:
251 cursor = IDBCursor::create(backend, m_cursorDirection, this, m_source.ge t(), m_transaction.get()); 265 cursor = IDBCursor::create(backend, m_cursorDirection, this, m_source.ge t(), m_transaction.get());
252 break; 266 break;
253 case IndexedDB::CursorKeyAndValue: 267 case IndexedDB::CursorKeyAndValue:
254 cursor = IDBCursorWithValue::create(backend, m_cursorDirection, this, m_ source.get(), m_transaction.get()); 268 cursor = IDBCursorWithValue::create(backend, m_cursorDirection, this, m_ source.get(), m_transaction.get());
255 break; 269 break;
256 default: 270 default:
257 ASSERT_NOT_REACHED(); 271 ASSERT_NOT_REACHED();
258 } 272 }
259 setResultCursor(cursor, key, primaryKey, value); 273 setResultCursor(cursor, key, primaryKey, value, blobInfo);
260 } 274 }
261 275
262 void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey) 276 void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
263 { 277 {
264 IDB_TRACE("IDBRequest::onSuccess(IDBKey)"); 278 IDB_TRACE("IDBRequest::onSuccess(IDBKey)");
265 if (!shouldEnqueueEvent()) 279 if (!shouldEnqueueEvent())
266 return; 280 return;
267 281
268 if (idbKey && idbKey->isValid()) 282 if (idbKey && idbKey->isValid())
269 onSuccessInternal(IDBAny::create(idbKey)); 283 onSuccessInternal(IDBAny::create(idbKey));
270 else 284 else
271 onSuccessInternal(IDBAny::createUndefined()); 285 onSuccessInternal(IDBAny::createUndefined());
272 } 286 }
273 287
274 void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer) 288 void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer, PassOwnPtr<Vect or<blink::WebBlobInfo> > blobInfo)
275 { 289 {
276 IDB_TRACE("IDBRequest::onSuccess(SharedBuffer)"); 290 IDB_TRACE("IDBRequest::onSuccess(SharedBuffer)");
277 if (!shouldEnqueueEvent()) 291 if (!shouldEnqueueEvent())
278 return; 292 return;
279 293
280 if (m_pendingCursor) { 294 if (m_pendingCursor) {
281 // Value should be null, signifying the end of the cursor's range. 295 // Value should be null, signifying the end of the cursor's range.
282 ASSERT(!valueBuffer.get()); 296 ASSERT(!valueBuffer.get());
297 ASSERT(!blobInfo->size());
283 m_pendingCursor->close(); 298 m_pendingCursor->close();
284 m_pendingCursor.clear(); 299 m_pendingCursor.clear();
285 } 300 }
286 301
287 onSuccessInternal(IDBAny::create(valueBuffer)); 302 ASSERT(!m_blobInfo.get());
303 m_blobInfo = blobInfo;
304 onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get()));
288 } 305 }
289 306
290 #ifndef NDEBUG 307 #ifndef NDEBUG
291 static PassRefPtr<IDBObjectStore> effectiveObjectStore(PassRefPtr<IDBAny> source ) 308 static PassRefPtr<IDBObjectStore> effectiveObjectStore(PassRefPtr<IDBAny> source )
292 { 309 {
293 if (source->type() == IDBAny::IDBObjectStoreType) 310 if (source->type() == IDBAny::IDBObjectStoreType)
294 return source->idbObjectStore(); 311 return source->idbObjectStore();
295 if (source->type() == IDBAny::IDBIndexType) 312 if (source->type() == IDBAny::IDBIndexType)
296 return source->idbIndex()->objectStore(); 313 return source->idbIndex()->objectStore();
297 314
298 ASSERT_NOT_REACHED(); 315 ASSERT_NOT_REACHED();
299 return nullptr; 316 return nullptr;
300 } 317 }
301 #endif 318 #endif
302 319
303 void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> prpValueBuffer, PassRefPtr<I DBKey> prpPrimaryKey, const IDBKeyPath& keyPath) 320 void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> prpValueBuffer, PassOwnPtr<V ector<blink::WebBlobInfo> > blobInfo, PassRefPtr<IDBKey> prpPrimaryKey, const ID BKeyPath& keyPath)
304 { 321 {
305 IDB_TRACE("IDBRequest::onSuccess(SharedBuffer, IDBKey, IDBKeyPath)"); 322 IDB_TRACE("IDBRequest::onSuccess(SharedBuffer, IDBKey, IDBKeyPath)");
306 if (!shouldEnqueueEvent()) 323 if (!shouldEnqueueEvent())
307 return; 324 return;
308 325
309 #ifndef NDEBUG 326 #ifndef NDEBUG
310 ASSERT(keyPath == effectiveObjectStore(m_source)->metadata().keyPath); 327 ASSERT(keyPath == effectiveObjectStore(m_source)->metadata().keyPath);
311 #endif 328 #endif
312 329
313 RefPtr<SharedBuffer> valueBuffer = prpValueBuffer; 330 RefPtr<SharedBuffer> valueBuffer = prpValueBuffer;
314 RefPtr<IDBKey> primaryKey = prpPrimaryKey; 331 RefPtr<IDBKey> primaryKey = prpPrimaryKey;
332 ASSERT(!m_blobInfo.get());
333 m_blobInfo = blobInfo;
315 334
316 #ifndef NDEBUG 335 #ifndef NDEBUG
317 assertPrimaryKeyValidOrInjectable(m_scriptState.get(), valueBuffer, primaryK ey, keyPath); 336 assertPrimaryKeyValidOrInjectable(m_scriptState.get(), valueBuffer, m_blobIn fo.get(), primaryKey, keyPath);
318 #endif 337 #endif
319 338
320 onSuccessInternal(IDBAny::create(valueBuffer, primaryKey, keyPath)); 339 onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get(), primaryKey, keyPath));
321 } 340 }
322 341
323 void IDBRequest::onSuccess(int64_t value) 342 void IDBRequest::onSuccess(int64_t value)
324 { 343 {
325 IDB_TRACE("IDBRequest::onSuccess(int64_t)"); 344 IDB_TRACE("IDBRequest::onSuccess(int64_t)");
326 if (!shouldEnqueueEvent()) 345 if (!shouldEnqueueEvent())
327 return; 346 return;
328 onSuccessInternal(IDBAny::create(value)); 347 onSuccessInternal(IDBAny::create(value));
329 } 348 }
330 349
(...skipping 12 matching lines...) Expand all
343 setResult(result); 362 setResult(result);
344 enqueueEvent(Event::create(EventTypeNames::success)); 363 enqueueEvent(Event::create(EventTypeNames::success));
345 } 364 }
346 365
347 void IDBRequest::setResult(PassRefPtr<IDBAny> result) 366 void IDBRequest::setResult(PassRefPtr<IDBAny> result)
348 { 367 {
349 m_result = result; 368 m_result = result;
350 m_resultDirty = true; 369 m_resultDirty = true;
351 } 370 }
352 371
353 void IDBRequest::onSuccess(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey , PassRefPtr<SharedBuffer> value) 372 void IDBRequest::onSuccess(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey , PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<blink::WebBlobInfo> > blobIn fo)
354 { 373 {
355 IDB_TRACE("IDBRequest::onSuccess(key, primaryKey, value)"); 374 IDB_TRACE("IDBRequest::onSuccess(key, primaryKey, value)");
356 if (!shouldEnqueueEvent()) 375 if (!shouldEnqueueEvent())
357 return; 376 return;
358 377
359 ASSERT(m_pendingCursor); 378 ASSERT(m_pendingCursor);
360 setResultCursor(m_pendingCursor.release(), key, primaryKey, value); 379 setResultCursor(m_pendingCursor.release(), key, primaryKey, value, blobInfo) ;
361 } 380 }
362 381
363 bool IDBRequest::hasPendingActivity() const 382 bool IDBRequest::hasPendingActivity() const
364 { 383 {
365 // FIXME: In an ideal world, we should return true as long as anyone has a o r can 384 // FIXME: In an ideal world, we should return true as long as anyone has a o r can
366 // get a handle to us and we have event listeners. This is order to h andle 385 // get a handle to us and we have event listeners. This is order to h andle
367 // user generated events properly. 386 // user generated events properly.
368 return m_hasPendingActivity && !m_contextStopped; 387 return m_hasPendingActivity && !m_contextStopped;
369 } 388 }
370 389
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 // this object to actually hold a reference to the database (to ensure 442 // this object to actually hold a reference to the database (to ensure
424 // it stays alive). 443 // it stays alive).
425 targets.append(m_transaction->db()); 444 targets.append(m_transaction->db());
426 } 445 }
427 446
428 // Cursor properties should not be updated until the success event is being dispatched. 447 // Cursor properties should not be updated until the success event is being dispatched.
429 RefPtr<IDBCursor> cursorToNotify; 448 RefPtr<IDBCursor> cursorToNotify;
430 if (event->type() == EventTypeNames::success) { 449 if (event->type() == EventTypeNames::success) {
431 cursorToNotify = getResultCursor(); 450 cursorToNotify = getResultCursor();
432 if (cursorToNotify) 451 if (cursorToNotify)
433 cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimary Key.release(), m_cursorValue.release()); 452 cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimary Key.release(), m_cursorValue.release(), m_blobInfo.release());
434 } 453 }
435 454
436 if (event->type() == EventTypeNames::upgradeneeded) { 455 if (event->type() == EventTypeNames::upgradeneeded) {
437 ASSERT(!m_didFireUpgradeNeededEvent); 456 ASSERT(!m_didFireUpgradeNeededEvent);
438 m_didFireUpgradeNeededEvent = true; 457 m_didFireUpgradeNeededEvent = true;
439 } 458 }
440 459
441 // FIXME: When we allow custom event dispatching, this will probably need to change. 460 // FIXME: When we allow custom event dispatching, this will probably need to change.
442 ASSERT_WITH_MESSAGE(event->type() == EventTypeNames::success || event->type( ) == EventTypeNames::error || event->type() == EventTypeNames::blocked || event- >type() == EventTypeNames::upgradeneeded, "event type was %s", event->type().utf 8().data()); 461 ASSERT_WITH_MESSAGE(event->type() == EventTypeNames::success || event->type( ) == EventTypeNames::error || event->type() == EventTypeNames::blocked || event- >type() == EventTypeNames::upgradeneeded, "event type was %s", event->type().utf 8().data());
443 const bool setTransactionActive = m_transaction && (event->type() == EventTy peNames::success || event->type() == EventTypeNames::upgradeneeded || (event->ty pe() == EventTypeNames::error && !m_requestAborted)); 462 const bool setTransactionActive = m_transaction && (event->type() == EventTy peNames::success || event->type() == EventTypeNames::upgradeneeded || (event->ty pe() == EventTypeNames::error && !m_requestAborted));
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 537
519 void IDBRequest::dequeueEvent(Event* event) 538 void IDBRequest::dequeueEvent(Event* event)
520 { 539 {
521 for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { 540 for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) {
522 if (m_enqueuedEvents[i].get() == event) 541 if (m_enqueuedEvents[i].get() == event)
523 m_enqueuedEvents.remove(i); 542 m_enqueuedEvents.remove(i);
524 } 543 }
525 } 544 }
526 545
527 } // namespace WebCore 546 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698