| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 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 are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 #include "core/dom/DOMException.h" | 36 #include "core/dom/DOMException.h" |
| 37 #include "core/dom/Document.h" | 37 #include "core/dom/Document.h" |
| 38 #include "core/dom/ExceptionCode.h" | 38 #include "core/dom/ExceptionCode.h" |
| 39 #include "core/events/EventQueue.h" | 39 #include "core/events/EventQueue.h" |
| 40 #include "modules/indexeddb/IDBDatabase.h" | 40 #include "modules/indexeddb/IDBDatabase.h" |
| 41 #include "modules/indexeddb/IDBDatabaseCallbacks.h" | 41 #include "modules/indexeddb/IDBDatabaseCallbacks.h" |
| 42 #include "modules/indexeddb/IDBKey.h" | 42 #include "modules/indexeddb/IDBKey.h" |
| 43 #include "modules/indexeddb/IDBKeyPath.h" | 43 #include "modules/indexeddb/IDBKeyPath.h" |
| 44 #include "modules/indexeddb/IDBMetadata.h" | 44 #include "modules/indexeddb/IDBMetadata.h" |
| 45 #include "modules/indexeddb/IDBObjectStore.h" | 45 #include "modules/indexeddb/IDBObjectStore.h" |
| 46 #include "modules/indexeddb/IDBTestHelper.h" |
| 46 #include "modules/indexeddb/IDBValue.h" | 47 #include "modules/indexeddb/IDBValue.h" |
| 47 #include "modules/indexeddb/IDBValueWrapping.h" | 48 #include "modules/indexeddb/IDBValueWrapping.h" |
| 48 #include "modules/indexeddb/MockWebIDBDatabase.h" | 49 #include "modules/indexeddb/MockWebIDBDatabase.h" |
| 49 #include "platform/SharedBuffer.h" | 50 #include "platform/SharedBuffer.h" |
| 50 #include "platform/wtf/PtrUtil.h" | 51 #include "platform/wtf/PtrUtil.h" |
| 51 #include "platform/wtf/RefPtr.h" | 52 #include "platform/wtf/RefPtr.h" |
| 52 #include "platform/wtf/Vector.h" | 53 #include "platform/wtf/Vector.h" |
| 53 #include "public/platform/Platform.h" | 54 #include "public/platform/Platform.h" |
| 54 #include "public/platform/WebURLLoaderMockFactory.h" | 55 #include "public/platform/WebURLLoaderMockFactory.h" |
| 55 #include "public/platform/WebURLResponse.h" | 56 #include "public/platform/WebURLResponse.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 | 111 |
| 111 WebURLLoaderMockFactory* url_loader_mock_factory_; | 112 WebURLLoaderMockFactory* url_loader_mock_factory_; |
| 112 Persistent<IDBDatabase> db_; | 113 Persistent<IDBDatabase> db_; |
| 113 Persistent<IDBTransaction> transaction_; | 114 Persistent<IDBTransaction> transaction_; |
| 114 Persistent<IDBObjectStore> store_; | 115 Persistent<IDBObjectStore> store_; |
| 115 | 116 |
| 116 static constexpr int64_t kTransactionId = 1234; | 117 static constexpr int64_t kTransactionId = 1234; |
| 117 static constexpr int64_t kStoreId = 5678; | 118 static constexpr int64_t kStoreId = 5678; |
| 118 }; | 119 }; |
| 119 | 120 |
| 120 // The created value is an array of true. If create_wrapped_value is true, the | |
| 121 // IDBValue's byte array will be wrapped in a Blob, otherwise it will not be. | |
| 122 RefPtr<IDBValue> CreateIDBValue(v8::Isolate* isolate, | |
| 123 bool create_wrapped_value) { | |
| 124 size_t element_count = create_wrapped_value ? 16 : 2; | |
| 125 v8::Local<v8::Array> v8_array = v8::Array::New(isolate, element_count); | |
| 126 for (size_t i = 0; i < element_count; ++i) | |
| 127 v8_array->Set(i, v8::True(isolate)); | |
| 128 | |
| 129 NonThrowableExceptionState non_throwable_exception_state; | |
| 130 IDBValueWrapper wrapper(isolate, v8_array, | |
| 131 SerializedScriptValue::SerializeOptions::kSerialize, | |
| 132 non_throwable_exception_state); | |
| 133 wrapper.WrapIfBiggerThan(create_wrapped_value ? 0 : 1024 * element_count); | |
| 134 | |
| 135 std::unique_ptr<Vector<RefPtr<BlobDataHandle>>> blob_data_handles = | |
| 136 WTF::MakeUnique<Vector<RefPtr<BlobDataHandle>>>(); | |
| 137 wrapper.ExtractBlobDataHandles(blob_data_handles.get()); | |
| 138 Vector<WebBlobInfo>& blob_infos = wrapper.WrappedBlobInfo(); | |
| 139 RefPtr<SharedBuffer> wrapped_marker_buffer = wrapper.ExtractWireBytes(); | |
| 140 IDBKey* key = IDBKey::CreateNumber(42.0); | |
| 141 IDBKeyPath key_path(String("primaryKey")); | |
| 142 | |
| 143 RefPtr<IDBValue> idb_value = IDBValue::Create( | |
| 144 std::move(wrapped_marker_buffer), std::move(blob_data_handles), | |
| 145 WTF::MakeUnique<Vector<WebBlobInfo>>(blob_infos), key, key_path); | |
| 146 | |
| 147 DCHECK_EQ(create_wrapped_value, | |
| 148 IDBValueUnwrapper::IsWrapped(idb_value.Get())); | |
| 149 return idb_value; | |
| 150 } | |
| 151 | |
| 152 TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) { | 121 TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) { |
| 153 V8TestingScope scope; | 122 V8TestingScope scope; |
| 154 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create(); | 123 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create(); |
| 155 EXPECT_CALL(*backend, Close()).Times(1); | 124 EXPECT_CALL(*backend, Close()).Times(1); |
| 156 BuildTransaction(scope, std::move(backend)); | 125 BuildTransaction(scope, std::move(backend)); |
| 157 | 126 |
| 158 PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions; | 127 PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions; |
| 159 live_transactions.insert(transaction_); | 128 live_transactions.insert(transaction_); |
| 160 | 129 |
| 161 ThreadState::Current()->CollectAllGarbage(); | 130 ThreadState::Current()->CollectAllGarbage(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 | 162 |
| 194 ThreadState::Current()->CollectAllGarbage(); | 163 ThreadState::Current()->CollectAllGarbage(); |
| 195 EXPECT_EQ(1U, live_transactions.size()); | 164 EXPECT_EQ(1U, live_transactions.size()); |
| 196 | 165 |
| 197 Persistent<IDBRequest> request = | 166 Persistent<IDBRequest> request = |
| 198 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), | 167 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), |
| 199 transaction_.Get(), IDBRequest::AsyncTraceState()); | 168 transaction_.Get(), IDBRequest::AsyncTraceState()); |
| 200 DeactivateNewTransactions(scope.GetIsolate()); | 169 DeactivateNewTransactions(scope.GetIsolate()); |
| 201 | 170 |
| 202 // This response should result in an event being enqueued immediately. | 171 // This response should result in an event being enqueued immediately. |
| 203 request->HandleResponse(CreateIDBValue(scope.GetIsolate(), false)); | 172 request->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), false)); |
| 204 | 173 |
| 205 request.Clear(); // The transaction is holding onto the request. | 174 request.Clear(); // The transaction is holding onto the request. |
| 206 ThreadState::Current()->CollectAllGarbage(); | 175 ThreadState::Current()->CollectAllGarbage(); |
| 207 EXPECT_EQ(1U, live_transactions.size()); | 176 EXPECT_EQ(1U, live_transactions.size()); |
| 208 | 177 |
| 209 // This will generate an Abort() call to the back end which is dropped by the | 178 // This will generate an Abort() call to the back end which is dropped by the |
| 210 // fake proxy, so an explicit OnAbort call is made. | 179 // fake proxy, so an explicit OnAbort call is made. |
| 211 scope.GetExecutionContext()->NotifyContextDestroyed(); | 180 scope.GetExecutionContext()->NotifyContextDestroyed(); |
| 212 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); | 181 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); |
| 213 transaction_.Clear(); | 182 transaction_.Clear(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 232 live_transactions.insert(transaction_); | 201 live_transactions.insert(transaction_); |
| 233 | 202 |
| 234 ThreadState::Current()->CollectAllGarbage(); | 203 ThreadState::Current()->CollectAllGarbage(); |
| 235 EXPECT_EQ(1U, live_transactions.size()); | 204 EXPECT_EQ(1U, live_transactions.size()); |
| 236 | 205 |
| 237 Persistent<IDBRequest> request = | 206 Persistent<IDBRequest> request = |
| 238 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), | 207 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), |
| 239 transaction_.Get(), IDBRequest::AsyncTraceState()); | 208 transaction_.Get(), IDBRequest::AsyncTraceState()); |
| 240 DeactivateNewTransactions(scope.GetIsolate()); | 209 DeactivateNewTransactions(scope.GetIsolate()); |
| 241 | 210 |
| 242 request->HandleResponse(CreateIDBValue(scope.GetIsolate(), true)); | 211 request->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true)); |
| 243 | 212 |
| 244 request.Clear(); // The transaction is holding onto the request. | 213 request.Clear(); // The transaction is holding onto the request. |
| 245 ThreadState::Current()->CollectAllGarbage(); | 214 ThreadState::Current()->CollectAllGarbage(); |
| 246 EXPECT_EQ(1U, live_transactions.size()); | 215 EXPECT_EQ(1U, live_transactions.size()); |
| 247 | 216 |
| 248 // This will generate an Abort() call to the back end which is dropped by the | 217 // This will generate an Abort() call to the back end which is dropped by the |
| 249 // fake proxy, so an explicit OnAbort call is made. | 218 // fake proxy, so an explicit OnAbort call is made. |
| 250 scope.GetExecutionContext()->NotifyContextDestroyed(); | 219 scope.GetExecutionContext()->NotifyContextDestroyed(); |
| 251 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); | 220 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); |
| 252 transaction_.Clear(); | 221 transaction_.Clear(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 271 EXPECT_EQ(1U, live_transactions.size()); | 240 EXPECT_EQ(1U, live_transactions.size()); |
| 272 | 241 |
| 273 Persistent<IDBRequest> request1 = | 242 Persistent<IDBRequest> request1 = |
| 274 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), | 243 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), |
| 275 transaction_.Get(), IDBRequest::AsyncTraceState()); | 244 transaction_.Get(), IDBRequest::AsyncTraceState()); |
| 276 Persistent<IDBRequest> request2 = | 245 Persistent<IDBRequest> request2 = |
| 277 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), | 246 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), |
| 278 transaction_.Get(), IDBRequest::AsyncTraceState()); | 247 transaction_.Get(), IDBRequest::AsyncTraceState()); |
| 279 DeactivateNewTransactions(scope.GetIsolate()); | 248 DeactivateNewTransactions(scope.GetIsolate()); |
| 280 | 249 |
| 281 request1->HandleResponse(CreateIDBValue(scope.GetIsolate(), true)); | 250 request1->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true)); |
| 282 request2->HandleResponse(CreateIDBValue(scope.GetIsolate(), true)); | 251 request2->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true)); |
| 283 | 252 |
| 284 request1.Clear(); // The transaction is holding onto the requests. | 253 request1.Clear(); // The transaction is holding onto the requests. |
| 285 request2.Clear(); | 254 request2.Clear(); |
| 286 ThreadState::Current()->CollectAllGarbage(); | 255 ThreadState::Current()->CollectAllGarbage(); |
| 287 EXPECT_EQ(1U, live_transactions.size()); | 256 EXPECT_EQ(1U, live_transactions.size()); |
| 288 | 257 |
| 289 // This will generate an Abort() call to the back end which is dropped by the | 258 // This will generate an Abort() call to the back end which is dropped by the |
| 290 // fake proxy, so an explicit OnAbort call is made. | 259 // fake proxy, so an explicit OnAbort call is made. |
| 291 scope.GetExecutionContext()->NotifyContextDestroyed(); | 260 scope.GetExecutionContext()->NotifyContextDestroyed(); |
| 292 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); | 261 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 314 EXPECT_EQ(1U, live_transactions.size()); | 283 EXPECT_EQ(1U, live_transactions.size()); |
| 315 | 284 |
| 316 Persistent<IDBRequest> request1 = | 285 Persistent<IDBRequest> request1 = |
| 317 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), | 286 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), |
| 318 transaction_.Get(), IDBRequest::AsyncTraceState()); | 287 transaction_.Get(), IDBRequest::AsyncTraceState()); |
| 319 Persistent<IDBRequest> request2 = | 288 Persistent<IDBRequest> request2 = |
| 320 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), | 289 IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()), |
| 321 transaction_.Get(), IDBRequest::AsyncTraceState()); | 290 transaction_.Get(), IDBRequest::AsyncTraceState()); |
| 322 DeactivateNewTransactions(scope.GetIsolate()); | 291 DeactivateNewTransactions(scope.GetIsolate()); |
| 323 | 292 |
| 324 request1->HandleResponse(CreateIDBValue(scope.GetIsolate(), true)); | 293 request1->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true)); |
| 325 request2->HandleResponse(CreateIDBValue(scope.GetIsolate(), false)); | 294 request2->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), false)); |
| 326 | 295 |
| 327 request1.Clear(); // The transaction is holding onto the requests. | 296 request1.Clear(); // The transaction is holding onto the requests. |
| 328 request2.Clear(); | 297 request2.Clear(); |
| 329 ThreadState::Current()->CollectAllGarbage(); | 298 ThreadState::Current()->CollectAllGarbage(); |
| 330 EXPECT_EQ(1U, live_transactions.size()); | 299 EXPECT_EQ(1U, live_transactions.size()); |
| 331 | 300 |
| 332 // This will generate an Abort() call to the back end which is dropped by the | 301 // This will generate an Abort() call to the back end which is dropped by the |
| 333 // fake proxy, so an explicit OnAbort call is made. | 302 // fake proxy, so an explicit OnAbort call is made. |
| 334 scope.GetDocument().Shutdown(); | 303 scope.GetDocument().Shutdown(); |
| 335 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); | 304 transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 // The test will not fail if it is, but ASAN would notice the error. | 343 // The test will not fail if it is, but ASAN would notice the error. |
| 375 db_->OnAbort(kTransactionId, DOMException::Create(kAbortError, "Aborted")); | 344 db_->OnAbort(kTransactionId, DOMException::Create(kAbortError, "Aborted")); |
| 376 | 345 |
| 377 // OnAbort() should have cleared the transaction's reference to the database. | 346 // OnAbort() should have cleared the transaction's reference to the database. |
| 378 ThreadState::Current()->CollectAllGarbage(); | 347 ThreadState::Current()->CollectAllGarbage(); |
| 379 EXPECT_EQ(0U, live_transactions.size()); | 348 EXPECT_EQ(0U, live_transactions.size()); |
| 380 } | 349 } |
| 381 | 350 |
| 382 } // namespace | 351 } // namespace |
| 383 } // namespace blink | 352 } // namespace blink |
| OLD | NEW |