2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "modules/indexeddb/InspectorIndexedDBAgent.h"
34 #include "bindings/core/v8/ExceptionState.h"
35 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
36 #include "bindings/core/v8/ScriptController.h"
37 #include "bindings/core/v8/ScriptState.h"
38 #include "core/dom/DOMStringList.h"
39 #include "core/dom/Document.h"
40 #include "core/events/EventListener.h"
41 #include "core/frame/LocalFrame.h"
42 #include "core/inspector/InspectorController.h"
43 #include "core/inspector/InspectorState.h"
44 #include "core/page/Page.h"
45 #include "modules/IndexedDBNames.h"
46 #include "modules/indexeddb/DOMWindowIndexedDatabase.h"
47 #include "modules/indexeddb/IDBCursor.h"
48 #include "modules/indexeddb/IDBCursorWithValue.h"
49 #include "modules/indexeddb/IDBDatabase.h"
50 #include "modules/indexeddb/IDBFactory.h"
51 #include "modules/indexeddb/IDBIndex.h"
52 #include "modules/indexeddb/IDBKey.h"
53 #include "modules/indexeddb/IDBKeyPath.h"
54 #include "modules/indexeddb/IDBKeyRange.h"
55 #include "modules/indexeddb/IDBMetadata.h"
56 #include "modules/indexeddb/IDBObjectStore.h"
57 #include "modules/indexeddb/IDBOpenDBRequest.h"
58 #include "modules/indexeddb/IDBPendingTransactionMonitor.h"
59 #include "modules/indexeddb/IDBRequest.h"
60 #include "modules/indexeddb/IDBTransaction.h"
61 #include "platform/JSONValues.h"
62 #include "platform/weborigin/SecurityOrigin.h"
63 #include "public/platform/WebIDBCursor.h"
64 #include "public/platform/WebIDBTypes.h"
65 #include "wtf/Vector.h"
67 using blink::TypeBuilder::Array;
68 using blink::TypeBuilder::IndexedDB::DatabaseWithObjectStores;
69 using blink::TypeBuilder::IndexedDB::DataEntry;
70 using blink::TypeBuilder::IndexedDB::Key;
71 using blink::TypeBuilder::IndexedDB::KeyPath;
72 using blink::TypeBuilder::IndexedDB::KeyRange;
73 using blink::TypeBuilder::IndexedDB::ObjectStore;
74 using blink::TypeBuilder::IndexedDB::ObjectStoreIndex;
76 typedef blink::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseNamesCallback RequestDatabaseNamesCallback;
77 typedef blink::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseCallback RequestDatabaseCallback;
78 typedef blink::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDataCallback RequestDataCallback;
79 typedef blink::InspectorBackendDispatcher::CallbackBase RequestCallback;
80 typedef blink::InspectorBackendDispatcher::IndexedDBCommandHandler::ClearObjectStoreCallback ClearObjectStoreCallback;
84 namespace IndexedDBAgentState {
85 static const char indexedDBAgentEnabled[] = "indexedDBAgentEnabled";
90 class GetDatabaseNamesCallback FINAL : public EventListener {
91 WTF_MAKE_NONCOPYABLE(GetDatabaseNamesCallback);
93 static PassRefPtr<GetDatabaseNamesCallback> create(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin)
95 return adoptRef(new GetDatabaseNamesCallback(requestCallback, securityOrigin));
98 virtual ~GetDatabaseNamesCallback() { }
100 virtual bool operator==(const EventListener& other) OVERRIDE
102 return this == &other;
105 virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE
107 if (!m_requestCallback->isActive())
109 if (event->type() != EventTypeNames::success) {
110 m_requestCallback->sendFailure("Unexpected event type.");
114 IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target());
115 IDBAny* requestResult = idbRequest->resultAsAny();
116 if (requestResult->type() != IDBAny::DOMStringListType) {
117 m_requestCallback->sendFailure("Unexpected result type.");
121 RefPtrWillBeRawPtr<DOMStringList> databaseNamesList = requestResult->domStringList();
122 RefPtr<TypeBuilder::Array<String> > databaseNames = TypeBuilder::Array<String>::create();
123 for (size_t i = 0; i < databaseNamesList->length(); ++i)
124 databaseNames->addItem(databaseNamesList->item(i));
125 m_requestCallback->sendSuccess(databaseNames.release());
129 GetDatabaseNamesCallback(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin)
130 : EventListener(EventListener::CPPEventListenerType)
131 , m_requestCallback(requestCallback)
132 , m_securityOrigin(securityOrigin) { }
133 RefPtr<RequestDatabaseNamesCallback> m_requestCallback;
134 String m_securityOrigin;
137 class ExecutableWithDatabase : public RefCounted<ExecutableWithDatabase> {
139 ExecutableWithDatabase(ScriptState* scriptState)
140 : m_scriptState(scriptState) { }
141 virtual ~ExecutableWithDatabase() { };
142 void start(IDBFactory*, SecurityOrigin*, const String& databaseName);
143 virtual void execute(IDBDatabase*) = 0;
144 virtual RequestCallback* requestCallback() = 0;
145 ExecutionContext* context() const { return m_scriptState->executionContext(); }
146 ScriptState* scriptState() const { return m_scriptState.get(); }
148 RefPtr<ScriptState> m_scriptState;
151 class OpenDatabaseCallback FINAL : public EventListener {
153 static PassRefPtr<OpenDatabaseCallback> create(ExecutableWithDatabase* executableWithDatabase)
155 return adoptRef(new OpenDatabaseCallback(executableWithDatabase));
158 virtual ~OpenDatabaseCallback() { }
160 virtual bool operator==(const EventListener& other) OVERRIDE
162 return this == &other;
165 virtual void handleEvent(ExecutionContext* context, Event* event) OVERRIDE
167 if (event->type() != EventTypeNames::success) {
168 m_executableWithDatabase->requestCallback()->sendFailure("Unexpected event type.");
172 IDBOpenDBRequest* idbOpenDBRequest = static_cast<IDBOpenDBRequest*>(event->target());
173 IDBAny* requestResult = idbOpenDBRequest->resultAsAny();
174 if (requestResult->type() != IDBAny::IDBDatabaseType) {
175 m_executableWithDatabase->requestCallback()->sendFailure("Unexpected result type.");
179 IDBDatabase* idbDatabase = requestResult->idbDatabase();
180 m_executableWithDatabase->execute(idbDatabase);
181 IDBPendingTransactionMonitor::from(*context).deactivateNewTransactions();
182 idbDatabase->close();
186 OpenDatabaseCallback(ExecutableWithDatabase* executableWithDatabase)
187 : EventListener(EventListener::CPPEventListenerType)
188 , m_executableWithDatabase(executableWithDatabase) { }
189 RefPtr<ExecutableWithDatabase> m_executableWithDatabase;
192 void ExecutableWithDatabase::start(IDBFactory* idbFactory, SecurityOrigin*, const String& databaseName)
194 RefPtr<OpenDatabaseCallback> callback = OpenDatabaseCallback::create(this);
195 TrackExceptionState exceptionState;
196 IDBOpenDBRequest* idbOpenDBRequest = idbFactory->open(scriptState(), databaseName, exceptionState);
197 if (exceptionState.hadException()) {
198 requestCallback()->sendFailure("Could not open database.");
201 idbOpenDBRequest->addEventListener(EventTypeNames::success, callback, false);
204 static IDBTransaction* transactionForDatabase(ExecutionContext* executionContext, IDBDatabase* idbDatabase, const String& objectStoreName, const String& mode = IndexedDBNames::readonly)
206 TrackExceptionState exceptionState;
207 IDBTransaction* idbTransaction = idbDatabase->transaction(executionContext, objectStoreName, mode, exceptionState);
208 if (exceptionState.hadException())
210 return idbTransaction;
213 static IDBObjectStore* objectStoreForTransaction(IDBTransaction* idbTransaction, const String& objectStoreName)
215 TrackExceptionState exceptionState;
216 IDBObjectStore* idbObjectStore = idbTransaction->objectStore(objectStoreName, exceptionState);
217 if (exceptionState.hadException())
219 return idbObjectStore;
222 static IDBIndex* indexForObjectStore(IDBObjectStore* idbObjectStore, const String& indexName)
224 TrackExceptionState exceptionState;
225 IDBIndex* idbIndex = idbObjectStore->index(indexName, exceptionState);
226 if (exceptionState.hadException())
231 static PassRefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath)
233 RefPtr<KeyPath> keyPath;
234 switch (idbKeyPath.type()) {
235 case IDBKeyPath::NullType:
236 keyPath = KeyPath::create().setType(KeyPath::Type::Null);
238 case IDBKeyPath::StringType:
239 keyPath = KeyPath::create().setType(KeyPath::Type::String);
240 keyPath->setString(idbKeyPath.string());
242 case IDBKeyPath::ArrayType: {
243 keyPath = KeyPath::create().setType(KeyPath::Type::Array);
244 RefPtr<TypeBuilder::Array<String> > array = TypeBuilder::Array<String>::create();
245 const Vector<String>& stringArray = idbKeyPath.array();
246 for (size_t i = 0; i < stringArray.size(); ++i)
247 array->addItem(stringArray[i]);
248 keyPath->setArray(array);
252 ASSERT_NOT_REACHED();
255 return keyPath.release();
258 class DatabaseLoader FINAL : public ExecutableWithDatabase {
260 static PassRefPtr<DatabaseLoader> create(ScriptState* scriptState, PassRefPtr<RequestDatabaseCallback> requestCallback)
262 return adoptRef(new DatabaseLoader(scriptState, requestCallback));
265 virtual ~DatabaseLoader() { }
267 virtual void execute(IDBDatabase* idbDatabase) OVERRIDE
269 if (!requestCallback()->isActive())
272 const IDBDatabaseMetadata databaseMetadata = idbDatabase->metadata();
274 RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore> > objectStores = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore>::create();
276 for (IDBDatabaseMetadata::ObjectStoreMap::const_iterator it = databaseMetadata.objectStores.begin(); it != databaseMetadata.objectStores.end(); ++it) {
277 const IDBObjectStoreMetadata& objectStoreMetadata = it->value;
279 RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex> > indexes = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex>::create();
281 for (IDBObjectStoreMetadata::IndexMap::const_iterator it = objectStoreMetadata.indexes.begin(); it != objectStoreMetadata.indexes.end(); ++it) {
282 const IDBIndexMetadata& indexMetadata = it->value;
284 RefPtr<ObjectStoreIndex> objectStoreIndex = ObjectStoreIndex::create()
285 .setName(indexMetadata.name)
286 .setKeyPath(keyPathFromIDBKeyPath(indexMetadata.keyPath))
287 .setUnique(indexMetadata.unique)
288 .setMultiEntry(indexMetadata.multiEntry);
289 indexes->addItem(objectStoreIndex);
292 RefPtr<ObjectStore> objectStore = ObjectStore::create()
293 .setName(objectStoreMetadata.name)
294 .setKeyPath(keyPathFromIDBKeyPath(objectStoreMetadata.keyPath))
295 .setAutoIncrement(objectStoreMetadata.autoIncrement)
296 .setIndexes(indexes);
297 objectStores->addItem(objectStore);
299 RefPtr<DatabaseWithObjectStores> result = DatabaseWithObjectStores::create()
300 .setName(databaseMetadata.name)
301 .setIntVersion(databaseMetadata.intVersion)
302 .setVersion(databaseMetadata.version)
303 .setObjectStores(objectStores);
305 m_requestCallback->sendSuccess(result);
308 virtual RequestCallback* requestCallback() OVERRIDE { return m_requestCallback.get(); }
310 DatabaseLoader(ScriptState* scriptState, PassRefPtr<RequestDatabaseCallback> requestCallback)
311 : ExecutableWithDatabase(scriptState)
312 , m_requestCallback(requestCallback) { }
313 RefPtr<RequestDatabaseCallback> m_requestCallback;
316 static IDBKey* idbKeyFromInspectorObject(JSONObject* key)
321 if (!key->getString("type", &type))
324 DEFINE_STATIC_LOCAL(String, number, ("number"));
325 DEFINE_STATIC_LOCAL(String, string, ("string"));
326 DEFINE_STATIC_LOCAL(String, date, ("date"));
327 DEFINE_STATIC_LOCAL(String, array, ("array"));
329 if (type == number) {
331 if (!key->getNumber("number", &number))
333 idbKey = IDBKey::createNumber(number);
334 } else if (type == string) {
336 if (!key->getString("string", &string))
338 idbKey = IDBKey::createString(string);
339 } else if (type == date) {
341 if (!key->getNumber("date", &date))
343 idbKey = IDBKey::createDate(date);
344 } else if (type == array) {
345 IDBKey::KeyArray keyArray;
346 RefPtr<JSONArray> array = key->getArray("array");
347 for (size_t i = 0; i < array->length(); ++i) {
348 RefPtr<JSONValue> value = array->get(i);
349 RefPtr<JSONObject> object;
350 if (!value->asObject(&object))
352 keyArray.append(idbKeyFromInspectorObject(object.get()));
354 idbKey = IDBKey::createArray(keyArray);
362 static IDBKeyRange* idbKeyRangeFromKeyRange(JSONObject* keyRange)
364 RefPtr<JSONObject> lower = keyRange->getObject("lower");
365 IDBKey* idbLower = lower ? idbKeyFromInspectorObject(lower.get()) : 0;
366 if (lower && !idbLower)
369 RefPtr<JSONObject> upper = keyRange->getObject("upper");
370 IDBKey* idbUpper = upper ? idbKeyFromInspectorObject(upper.get()) : 0;
371 if (upper && !idbUpper)
375 if (!keyRange->getBoolean("lowerOpen", &lowerOpen))
377 IDBKeyRange::LowerBoundType lowerBoundType = lowerOpen ? IDBKeyRange::LowerBoundOpen : IDBKeyRange::LowerBoundClosed;
380 if (!keyRange->getBoolean("upperOpen", &upperOpen))
382 IDBKeyRange::UpperBoundType upperBoundType = upperOpen ? IDBKeyRange::UpperBoundOpen : IDBKeyRange::UpperBoundClosed;
384 return IDBKeyRange::create(idbLower, idbUpper, lowerBoundType, upperBoundType);
389 class OpenCursorCallback FINAL : public EventListener {
391 static PassRefPtr<OpenCursorCallback> create(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize)
393 return adoptRef(new OpenCursorCallback(scriptState, requestCallback, skipCount, pageSize));
396 virtual ~OpenCursorCallback() { }
398 virtual bool operator==(const EventListener& other) OVERRIDE
400 return this == &other;
403 virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE
405 if (event->type() != EventTypeNames::success) {
406 m_requestCallback->sendFailure("Unexpected event type.");
410 IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target());
411 IDBAny* requestResult = idbRequest->resultAsAny();
412 if (requestResult->type() == IDBAny::BufferType) {
416 if (requestResult->type() != IDBAny::IDBCursorWithValueType) {
417 m_requestCallback->sendFailure("Unexpected result type.");
421 IDBCursorWithValue* idbCursor = requestResult->idbCursorWithValue();
424 TrackExceptionState exceptionState;
425 idbCursor->advance(m_skipCount, exceptionState);
426 if (exceptionState.hadException())
427 m_requestCallback->sendFailure("Could not advance cursor.");
432 if (m_result->length() == m_pageSize) {
437 // Continue cursor before making injected script calls, otherwise transaction might be finished.
438 TrackExceptionState exceptionState;
439 idbCursor->continueFunction(0, 0, exceptionState);
440 if (exceptionState.hadException()) {
441 m_requestCallback->sendFailure("Could not continue cursor.");
445 Document* document = toDocument(m_scriptState->executionContext());
448 RefPtr<DataEntry> dataEntry = DataEntry::create()
449 .setKey(idbCursor->key(m_scriptState.get()).toJSONValue(m_scriptState.get())->toJSONString())
450 .setPrimaryKey(idbCursor->primaryKey(m_scriptState.get()).toJSONValue(m_scriptState.get())->toJSONString())
451 .setValue(idbCursor->value(m_scriptState.get()).toJSONValue(m_scriptState.get())->toJSONString());
452 m_result->addItem(dataEntry);
456 void end(bool hasMore)
458 if (!m_requestCallback->isActive())
460 m_requestCallback->sendSuccess(m_result.release(), hasMore);
464 OpenCursorCallback(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize)
465 : EventListener(EventListener::CPPEventListenerType)
466 , m_scriptState(scriptState)
467 , m_requestCallback(requestCallback)
468 , m_skipCount(skipCount)
469 , m_pageSize(pageSize)
471 m_result = Array<DataEntry>::create();
474 RefPtr<ScriptState> m_scriptState;
475 RefPtr<RequestDataCallback> m_requestCallback;
478 RefPtr<Array<DataEntry> > m_result;
481 class DataLoader FINAL : public ExecutableWithDatabase {
483 static PassRefPtr<DataLoader> create(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, const String& objectStoreName, const String& indexName, IDBKeyRange* idbKeyRange, int skipCount, unsigned pageSize)
485 return adoptRef(new DataLoader(scriptState, requestCallback, objectStoreName, indexName, idbKeyRange, skipCount, pageSize));
488 virtual ~DataLoader() { }
490 virtual void execute(IDBDatabase* idbDatabase) OVERRIDE
492 if (!requestCallback()->isActive())
494 IDBTransaction* idbTransaction = transactionForDatabase(context(), idbDatabase, m_objectStoreName);
495 if (!idbTransaction) {
496 m_requestCallback->sendFailure("Could not get transaction");
499 IDBObjectStore* idbObjectStore = objectStoreForTransaction(idbTransaction, m_objectStoreName);
500 if (!idbObjectStore) {
501 m_requestCallback->sendFailure("Could not get object store");
505 RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(scriptState(), m_requestCallback, m_skipCount, m_pageSize);
507 IDBRequest* idbRequest;
508 if (!m_indexName.isEmpty()) {
509 IDBIndex* idbIndex = indexForObjectStore(idbObjectStore, m_indexName);
511 m_requestCallback->sendFailure("Could not get index");
515 idbRequest = idbIndex->openCursor(scriptState(), m_idbKeyRange.get(), WebIDBCursorDirectionNext);
517 idbRequest = idbObjectStore->openCursor(scriptState(), m_idbKeyRange.get(), WebIDBCursorDirectionNext);
519 idbRequest->addEventListener(EventTypeNames::success, openCursorCallback, false);
522 virtual RequestCallback* requestCallback() OVERRIDE { return m_requestCallback.get(); }
523 DataLoader(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, const String& objectStoreName, const String& indexName, IDBKeyRange* idbKeyRange, int skipCount, unsigned pageSize)
524 : ExecutableWithDatabase(scriptState)
525 , m_requestCallback(requestCallback)
526 , m_objectStoreName(objectStoreName)
527 , m_indexName(indexName)
528 , m_idbKeyRange(idbKeyRange)
529 , m_skipCount(skipCount)
530 , m_pageSize(pageSize)
534 RefPtr<RequestDataCallback> m_requestCallback;
535 String m_objectStoreName;
537 Persistent<IDBKeyRange> m_idbKeyRange;
542 LocalFrame* findFrameWithSecurityOrigin(Page* page, const String& securityOrigin)
544 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
545 if (!frame->isLocalFrame())
547 RefPtr<SecurityOrigin> documentOrigin = toLocalFrame(frame)->document()->securityOrigin();
548 if (documentOrigin->toRawString() == securityOrigin)
549 return toLocalFrame(frame);
556 void InspectorIndexedDBAgent::provideTo(Page* page)
558 OwnPtrWillBeRawPtr<InspectorIndexedDBAgent> agent(adoptPtrWillBeNoop(new InspectorIndexedDBAgent(page)));
559 page->inspectorController().registerModuleAgent(agent.release());
562 InspectorIndexedDBAgent::InspectorIndexedDBAgent(Page* page)
563 : InspectorBaseAgent<InspectorIndexedDBAgent>("IndexedDB")
568 InspectorIndexedDBAgent::~InspectorIndexedDBAgent()
572 void InspectorIndexedDBAgent::clearFrontend()
577 void InspectorIndexedDBAgent::restore()
579 if (m_state->getBoolean(IndexedDBAgentState::indexedDBAgentEnabled)) {
585 void InspectorIndexedDBAgent::enable(ErrorString*)
587 m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, true);
590 void InspectorIndexedDBAgent::disable(ErrorString*)
592 m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, false);
595 static Document* assertDocument(ErrorString* errorString, LocalFrame* frame)
597 Document* document = frame ? frame->document() : 0;
600 *errorString = "No document for given frame found";
605 static IDBFactory* assertIDBFactory(ErrorString* errorString, Document* document)
607 LocalDOMWindow* domWindow = document->domWindow();
609 *errorString = "No IndexedDB factory for given frame found";
612 IDBFactory* idbFactory = DOMWindowIndexedDatabase::indexedDB(*domWindow);
615 *errorString = "No IndexedDB factory for given frame found";
620 void InspectorIndexedDBAgent::requestDatabaseNames(ErrorString* errorString, const String& securityOrigin, PassRefPtr<RequestDatabaseNamesCallback> requestCallback)
622 LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin);
623 Document* document = assertDocument(errorString, frame);
626 IDBFactory* idbFactory = assertIDBFactory(errorString, document);
630 ScriptState* scriptState = ScriptState::forMainWorld(frame);
631 ScriptState::Scope scope(scriptState);
632 TrackExceptionState exceptionState;
633 IDBRequest* idbRequest = idbFactory->getDatabaseNames(scriptState, exceptionState);
634 if (exceptionState.hadException()) {
635 requestCallback->sendFailure("Could not obtain database names.");
638 idbRequest->addEventListener(EventTypeNames::success, GetDatabaseNamesCallback::create(requestCallback, document->securityOrigin()->toRawString()), false);
641 void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, const String& securityOrigin, const String& databaseName, PassRefPtr<RequestDatabaseCallback> requestCallback)
643 LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin);
644 Document* document = assertDocument(errorString, frame);
647 IDBFactory* idbFactory = assertIDBFactory(errorString, document);
651 ScriptState* scriptState = ScriptState::forMainWorld(frame);
652 ScriptState::Scope scope(scriptState);
653 RefPtr<DatabaseLoader> databaseLoader = DatabaseLoader::create(scriptState, requestCallback);
654 databaseLoader->start(idbFactory, document->securityOrigin(), databaseName);
657 void InspectorIndexedDBAgent::requestData(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<JSONObject>* keyRange, PassRefPtr<RequestDataCallback> requestCallback)
659 LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin);
660 Document* document = assertDocument(errorString, frame);
663 IDBFactory* idbFactory = assertIDBFactory(errorString, document);
667 IDBKeyRange* idbKeyRange = keyRange ? idbKeyRangeFromKeyRange(keyRange->get()) : 0;
668 if (keyRange && !idbKeyRange) {
669 *errorString = "Can not parse key range.";
673 ScriptState* scriptState = ScriptState::forMainWorld(frame);
674 ScriptState::Scope scope(scriptState);
675 RefPtr<DataLoader> dataLoader = DataLoader::create(scriptState, requestCallback, objectStoreName, indexName, idbKeyRange, skipCount, pageSize);
676 dataLoader->start(idbFactory, document->securityOrigin(), databaseName);
679 class ClearObjectStoreListener FINAL : public EventListener {
680 WTF_MAKE_NONCOPYABLE(ClearObjectStoreListener);
682 static PassRefPtr<ClearObjectStoreListener> create(PassRefPtr<ClearObjectStoreCallback> requestCallback)
684 return adoptRef(new ClearObjectStoreListener(requestCallback));
687 virtual ~ClearObjectStoreListener() { }
689 virtual bool operator==(const EventListener& other) OVERRIDE
691 return this == &other;
694 virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE
696 if (!m_requestCallback->isActive())
698 if (event->type() != EventTypeNames::complete) {
699 m_requestCallback->sendFailure("Unexpected event type.");
703 m_requestCallback->sendSuccess();
706 ClearObjectStoreListener(PassRefPtr<ClearObjectStoreCallback> requestCallback)
707 : EventListener(EventListener::CPPEventListenerType)
708 , m_requestCallback(requestCallback)
712 RefPtr<ClearObjectStoreCallback> m_requestCallback;
716 class ClearObjectStore FINAL : public ExecutableWithDatabase {
718 static PassRefPtr<ClearObjectStore> create(ScriptState* scriptState, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
720 return adoptRef(new ClearObjectStore(scriptState, objectStoreName, requestCallback));
723 ClearObjectStore(ScriptState* scriptState, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
724 : ExecutableWithDatabase(scriptState)
725 , m_objectStoreName(objectStoreName)
726 , m_requestCallback(requestCallback)
730 virtual void execute(IDBDatabase* idbDatabase) OVERRIDE
732 if (!requestCallback()->isActive())
734 IDBTransaction* idbTransaction = transactionForDatabase(context(), idbDatabase, m_objectStoreName, IndexedDBNames::readwrite);
735 if (!idbTransaction) {
736 m_requestCallback->sendFailure("Could not get transaction");
739 IDBObjectStore* idbObjectStore = objectStoreForTransaction(idbTransaction, m_objectStoreName);
740 if (!idbObjectStore) {
741 m_requestCallback->sendFailure("Could not get object store");
745 TrackExceptionState exceptionState;
746 idbObjectStore->clear(scriptState(), exceptionState);
747 ASSERT(!exceptionState.hadException());
748 if (exceptionState.hadException()) {
749 ExceptionCode ec = exceptionState.code();
750 m_requestCallback->sendFailure(String::format("Could not clear object store '%s': %d", m_objectStoreName.utf8().data(), ec));
753 idbTransaction->addEventListener(EventTypeNames::complete, ClearObjectStoreListener::create(m_requestCallback), false);
756 virtual RequestCallback* requestCallback() OVERRIDE { return m_requestCallback.get(); }
758 const String m_objectStoreName;
759 RefPtr<ClearObjectStoreCallback> m_requestCallback;
762 void InspectorIndexedDBAgent::clearObjectStore(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
764 LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin);
765 Document* document = assertDocument(errorString, frame);
768 IDBFactory* idbFactory = assertIDBFactory(errorString, document);
772 ScriptState* scriptState = ScriptState::forMainWorld(frame);
773 ScriptState::Scope scope(scriptState);
774 RefPtr<ClearObjectStore> clearObjectStore = ClearObjectStore::create(scriptState, objectStoreName, requestCallback);
775 clearObjectStore->start(idbFactory, document->securityOrigin(), databaseName);
778 void InspectorIndexedDBAgent::trace(Visitor* visitor)
780 visitor->trace(m_page);
781 InspectorBaseAgent::trace(visitor);