InspectorIndexedDBAgent.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. /*
  2. * Copyright (C) 2012 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  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
  13. * distribution.
  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.
  17. *
  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.
  29. */
  30. #include "config.h"
  31. #if ENABLE(INSPECTOR) && ENABLE(INDEXED_DATABASE)
  32. #include "InspectorIndexedDBAgent.h"
  33. #include "DOMStringList.h"
  34. #include "DOMWindow.h"
  35. #include "DOMWindowIndexedDatabase.h"
  36. #include "Document.h"
  37. #include "Event.h"
  38. #include "EventListener.h"
  39. #include "EventTarget.h"
  40. #include "ExceptionCode.h"
  41. #include "Frame.h"
  42. #include "IDBCursor.h"
  43. #include "IDBCursorWithValue.h"
  44. #include "IDBDatabase.h"
  45. #include "IDBDatabaseCallbacks.h"
  46. #include "IDBFactory.h"
  47. #include "IDBIndex.h"
  48. #include "IDBKey.h"
  49. #include "IDBKeyPath.h"
  50. #include "IDBKeyRange.h"
  51. #include "IDBMetadata.h"
  52. #include "IDBObjectStore.h"
  53. #include "IDBOpenDBRequest.h"
  54. #include "IDBPendingTransactionMonitor.h"
  55. #include "IDBRequest.h"
  56. #include "IDBTransaction.h"
  57. #include "InjectedScript.h"
  58. #include "InspectorFrontend.h"
  59. #include "InspectorPageAgent.h"
  60. #include "InspectorState.h"
  61. #include "InspectorValues.h"
  62. #include "InstrumentingAgents.h"
  63. #include "SecurityOrigin.h"
  64. #include <wtf/Vector.h>
  65. using WebCore::TypeBuilder::Array;
  66. using WebCore::TypeBuilder::IndexedDB::DatabaseWithObjectStores;
  67. using WebCore::TypeBuilder::IndexedDB::DataEntry;
  68. using WebCore::TypeBuilder::IndexedDB::Key;
  69. using WebCore::TypeBuilder::IndexedDB::KeyPath;
  70. using WebCore::TypeBuilder::IndexedDB::KeyRange;
  71. using WebCore::TypeBuilder::IndexedDB::ObjectStore;
  72. using WebCore::TypeBuilder::IndexedDB::ObjectStoreIndex;
  73. typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseNamesCallback RequestDatabaseNamesCallback;
  74. typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseCallback RequestDatabaseCallback;
  75. typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDataCallback RequestDataCallback;
  76. typedef WebCore::InspectorBackendDispatcher::CallbackBase RequestCallback;
  77. typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::ClearObjectStoreCallback ClearObjectStoreCallback;
  78. namespace WebCore {
  79. namespace IndexedDBAgentState {
  80. static const char indexedDBAgentEnabled[] = "indexedDBAgentEnabled";
  81. };
  82. namespace {
  83. class GetDatabaseNamesCallback : public EventListener {
  84. WTF_MAKE_NONCOPYABLE(GetDatabaseNamesCallback);
  85. public:
  86. static PassRefPtr<GetDatabaseNamesCallback> create(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin)
  87. {
  88. return adoptRef(new GetDatabaseNamesCallback(requestCallback, securityOrigin));
  89. }
  90. virtual ~GetDatabaseNamesCallback() { }
  91. virtual bool operator==(const EventListener& other) OVERRIDE
  92. {
  93. return this == &other;
  94. }
  95. virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
  96. {
  97. if (!m_requestCallback->isActive())
  98. return;
  99. if (event->type() != eventNames().successEvent) {
  100. m_requestCallback->sendFailure("Unexpected event type.");
  101. return;
  102. }
  103. IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target());
  104. ExceptionCode ec = 0;
  105. RefPtr<IDBAny> requestResult = idbRequest->result(ec);
  106. if (ec) {
  107. m_requestCallback->sendFailure("Could not get result in callback.");
  108. return;
  109. }
  110. if (requestResult->type() != IDBAny::DOMStringListType) {
  111. m_requestCallback->sendFailure("Unexpected result type.");
  112. return;
  113. }
  114. RefPtr<DOMStringList> databaseNamesList = requestResult->domStringList();
  115. RefPtr<TypeBuilder::Array<String> > databaseNames = TypeBuilder::Array<String>::create();
  116. for (size_t i = 0; i < databaseNamesList->length(); ++i)
  117. databaseNames->addItem(databaseNamesList->item(i));
  118. m_requestCallback->sendSuccess(databaseNames.release());
  119. }
  120. private:
  121. GetDatabaseNamesCallback(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin)
  122. : EventListener(EventListener::CPPEventListenerType)
  123. , m_requestCallback(requestCallback)
  124. , m_securityOrigin(securityOrigin) { }
  125. RefPtr<RequestDatabaseNamesCallback> m_requestCallback;
  126. String m_securityOrigin;
  127. };
  128. class ExecutableWithDatabase : public RefCounted<ExecutableWithDatabase> {
  129. public:
  130. ExecutableWithDatabase(ScriptExecutionContext* context)
  131. : m_context(context) { }
  132. virtual ~ExecutableWithDatabase() { };
  133. void start(IDBFactory*, SecurityOrigin*, const String& databaseName);
  134. virtual void execute(PassRefPtr<IDBDatabase>) = 0;
  135. virtual RequestCallback* requestCallback() = 0;
  136. ScriptExecutionContext* context() { return m_context; };
  137. private:
  138. ScriptExecutionContext* m_context;
  139. };
  140. class OpenDatabaseCallback : public EventListener {
  141. public:
  142. static PassRefPtr<OpenDatabaseCallback> create(ExecutableWithDatabase* executableWithDatabase)
  143. {
  144. return adoptRef(new OpenDatabaseCallback(executableWithDatabase));
  145. }
  146. virtual ~OpenDatabaseCallback() { }
  147. virtual bool operator==(const EventListener& other) OVERRIDE
  148. {
  149. return this == &other;
  150. }
  151. virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
  152. {
  153. if (event->type() != eventNames().successEvent) {
  154. m_executableWithDatabase->requestCallback()->sendFailure("Unexpected event type.");
  155. return;
  156. }
  157. IDBOpenDBRequest* idbOpenDBRequest = static_cast<IDBOpenDBRequest*>(event->target());
  158. ExceptionCode ec = 0;
  159. RefPtr<IDBAny> requestResult = idbOpenDBRequest->result(ec);
  160. if (ec) {
  161. m_executableWithDatabase->requestCallback()->sendFailure("Could not get result in callback.");
  162. return;
  163. }
  164. if (requestResult->type() != IDBAny::IDBDatabaseType) {
  165. m_executableWithDatabase->requestCallback()->sendFailure("Unexpected result type.");
  166. return;
  167. }
  168. RefPtr<IDBDatabase> idbDatabase = requestResult->idbDatabase();
  169. m_executableWithDatabase->execute(idbDatabase);
  170. IDBPendingTransactionMonitor::deactivateNewTransactions();
  171. idbDatabase->close();
  172. }
  173. private:
  174. OpenDatabaseCallback(ExecutableWithDatabase* executableWithDatabase)
  175. : EventListener(EventListener::CPPEventListenerType)
  176. , m_executableWithDatabase(executableWithDatabase) { }
  177. RefPtr<ExecutableWithDatabase> m_executableWithDatabase;
  178. };
  179. void ExecutableWithDatabase::start(IDBFactory* idbFactory, SecurityOrigin*, const String& databaseName)
  180. {
  181. RefPtr<OpenDatabaseCallback> callback = OpenDatabaseCallback::create(this);
  182. ExceptionCode ec = 0;
  183. RefPtr<IDBOpenDBRequest> idbOpenDBRequest = idbFactory->open(context(), databaseName, ec);
  184. if (ec) {
  185. requestCallback()->sendFailure("Could not open database.");
  186. return;
  187. }
  188. idbOpenDBRequest->addEventListener(eventNames().successEvent, callback, false);
  189. }
  190. static PassRefPtr<IDBTransaction> transactionForDatabase(ScriptExecutionContext* scriptExecutionContext, IDBDatabase* idbDatabase, const String& objectStoreName, const String& mode = IDBTransaction::modeReadOnly())
  191. {
  192. ExceptionCode ec = 0;
  193. RefPtr<IDBTransaction> idbTransaction = idbDatabase->transaction(scriptExecutionContext, objectStoreName, mode, ec);
  194. if (ec)
  195. return 0;
  196. return idbTransaction;
  197. }
  198. static PassRefPtr<IDBObjectStore> objectStoreForTransaction(IDBTransaction* idbTransaction, const String& objectStoreName)
  199. {
  200. ExceptionCode ec = 0;
  201. RefPtr<IDBObjectStore> idbObjectStore = idbTransaction->objectStore(objectStoreName, ec);
  202. if (ec)
  203. return 0;
  204. return idbObjectStore;
  205. }
  206. static PassRefPtr<IDBIndex> indexForObjectStore(IDBObjectStore* idbObjectStore, const String& indexName)
  207. {
  208. ExceptionCode ec = 0;
  209. RefPtr<IDBIndex> idbIndex = idbObjectStore->index(indexName, ec);
  210. if (ec)
  211. return 0;
  212. return idbIndex;
  213. }
  214. static PassRefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath)
  215. {
  216. RefPtr<KeyPath> keyPath;
  217. switch (idbKeyPath.type()) {
  218. case IDBKeyPath::NullType:
  219. keyPath = KeyPath::create().setType(KeyPath::Type::Null);
  220. break;
  221. case IDBKeyPath::StringType:
  222. keyPath = KeyPath::create().setType(KeyPath::Type::String);
  223. keyPath->setString(idbKeyPath.string());
  224. break;
  225. case IDBKeyPath::ArrayType: {
  226. keyPath = KeyPath::create().setType(KeyPath::Type::Array);
  227. RefPtr<TypeBuilder::Array<String> > array = TypeBuilder::Array<String>::create();
  228. const Vector<String>& stringArray = idbKeyPath.array();
  229. for (size_t i = 0; i < stringArray.size(); ++i)
  230. array->addItem(stringArray[i]);
  231. keyPath->setArray(array);
  232. break;
  233. }
  234. default:
  235. ASSERT_NOT_REACHED();
  236. }
  237. return keyPath.release();
  238. }
  239. class DatabaseLoader : public ExecutableWithDatabase {
  240. public:
  241. static PassRefPtr<DatabaseLoader> create(ScriptExecutionContext* context, PassRefPtr<RequestDatabaseCallback> requestCallback)
  242. {
  243. return adoptRef(new DatabaseLoader(context, requestCallback));
  244. }
  245. virtual ~DatabaseLoader() { }
  246. virtual void execute(PassRefPtr<IDBDatabase> prpDatabase)
  247. {
  248. RefPtr<IDBDatabase> idbDatabase = prpDatabase;
  249. if (!requestCallback()->isActive())
  250. return;
  251. const IDBDatabaseMetadata databaseMetadata = idbDatabase->metadata();
  252. RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore> > objectStores = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore>::create();
  253. for (IDBDatabaseMetadata::ObjectStoreMap::const_iterator it = databaseMetadata.objectStores.begin(); it != databaseMetadata.objectStores.end(); ++it) {
  254. const IDBObjectStoreMetadata& objectStoreMetadata = it->value;
  255. RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex> > indexes = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex>::create();
  256. for (IDBObjectStoreMetadata::IndexMap::const_iterator it = objectStoreMetadata.indexes.begin(); it != objectStoreMetadata.indexes.end(); ++it) {
  257. const IDBIndexMetadata& indexMetadata = it->value;
  258. RefPtr<ObjectStoreIndex> objectStoreIndex = ObjectStoreIndex::create()
  259. .setName(indexMetadata.name)
  260. .setKeyPath(keyPathFromIDBKeyPath(indexMetadata.keyPath))
  261. .setUnique(indexMetadata.unique)
  262. .setMultiEntry(indexMetadata.multiEntry);
  263. indexes->addItem(objectStoreIndex);
  264. }
  265. RefPtr<ObjectStore> objectStore = ObjectStore::create()
  266. .setName(objectStoreMetadata.name)
  267. .setKeyPath(keyPathFromIDBKeyPath(objectStoreMetadata.keyPath))
  268. .setAutoIncrement(objectStoreMetadata.autoIncrement)
  269. .setIndexes(indexes);
  270. objectStores->addItem(objectStore);
  271. }
  272. RefPtr<DatabaseWithObjectStores> result = DatabaseWithObjectStores::create()
  273. .setName(databaseMetadata.name)
  274. .setIntVersion(databaseMetadata.intVersion)
  275. .setVersion(databaseMetadata.version)
  276. .setObjectStores(objectStores);
  277. m_requestCallback->sendSuccess(result);
  278. }
  279. virtual RequestCallback* requestCallback() { return m_requestCallback.get(); }
  280. private:
  281. DatabaseLoader(ScriptExecutionContext* context, PassRefPtr<RequestDatabaseCallback> requestCallback)
  282. : ExecutableWithDatabase(context)
  283. , m_requestCallback(requestCallback) { }
  284. RefPtr<RequestDatabaseCallback> m_requestCallback;
  285. };
  286. static PassRefPtr<IDBKey> idbKeyFromInspectorObject(InspectorObject* key)
  287. {
  288. RefPtr<IDBKey> idbKey;
  289. String type;
  290. if (!key->getString("type", &type))
  291. return 0;
  292. DEFINE_STATIC_LOCAL(String, number, (ASCIILiteral("number")));
  293. DEFINE_STATIC_LOCAL(String, string, (ASCIILiteral("string")));
  294. DEFINE_STATIC_LOCAL(String, date, (ASCIILiteral("date")));
  295. DEFINE_STATIC_LOCAL(String, array, (ASCIILiteral("array")));
  296. if (type == number) {
  297. double number;
  298. if (!key->getNumber("number", &number))
  299. return 0;
  300. idbKey = IDBKey::createNumber(number);
  301. } else if (type == string) {
  302. String string;
  303. if (!key->getString("string", &string))
  304. return 0;
  305. idbKey = IDBKey::createString(string);
  306. } else if (type == date) {
  307. double date;
  308. if (!key->getNumber("date", &date))
  309. return 0;
  310. idbKey = IDBKey::createDate(date);
  311. } else if (type == array) {
  312. IDBKey::KeyArray keyArray;
  313. RefPtr<InspectorArray> array = key->getArray("array");
  314. for (size_t i = 0; i < array->length(); ++i) {
  315. RefPtr<InspectorValue> value = array->get(i);
  316. RefPtr<InspectorObject> object;
  317. if (!value->asObject(&object))
  318. return 0;
  319. keyArray.append(idbKeyFromInspectorObject(object.get()));
  320. }
  321. idbKey = IDBKey::createArray(keyArray);
  322. } else
  323. return 0;
  324. return idbKey.release();
  325. }
  326. static PassRefPtr<IDBKeyRange> idbKeyRangeFromKeyRange(InspectorObject* keyRange)
  327. {
  328. RefPtr<InspectorObject> lower = keyRange->getObject("lower");
  329. RefPtr<IDBKey> idbLower = lower ? idbKeyFromInspectorObject(lower.get()) : 0;
  330. if (lower && !idbLower)
  331. return 0;
  332. RefPtr<InspectorObject> upper = keyRange->getObject("upper");
  333. RefPtr<IDBKey> idbUpper = upper ? idbKeyFromInspectorObject(upper.get()) : 0;
  334. if (upper && !idbUpper)
  335. return 0;
  336. bool lowerOpen;
  337. if (!keyRange->getBoolean("lowerOpen", &lowerOpen))
  338. return 0;
  339. IDBKeyRange::LowerBoundType lowerBoundType = lowerOpen ? IDBKeyRange::LowerBoundOpen : IDBKeyRange::LowerBoundClosed;
  340. bool upperOpen;
  341. if (!keyRange->getBoolean("upperOpen", &upperOpen))
  342. return 0;
  343. IDBKeyRange::UpperBoundType upperBoundType = upperOpen ? IDBKeyRange::UpperBoundOpen : IDBKeyRange::UpperBoundClosed;
  344. RefPtr<IDBKeyRange> idbKeyRange = IDBKeyRange::create(idbLower, idbUpper, lowerBoundType, upperBoundType);
  345. return idbKeyRange.release();
  346. }
  347. class DataLoader;
  348. class OpenCursorCallback : public EventListener {
  349. public:
  350. static PassRefPtr<OpenCursorCallback> create(InjectedScript injectedScript, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize)
  351. {
  352. return adoptRef(new OpenCursorCallback(injectedScript, requestCallback, skipCount, pageSize));
  353. }
  354. virtual ~OpenCursorCallback() { }
  355. virtual bool operator==(const EventListener& other) OVERRIDE
  356. {
  357. return this == &other;
  358. }
  359. virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
  360. {
  361. if (event->type() != eventNames().successEvent) {
  362. m_requestCallback->sendFailure("Unexpected event type.");
  363. return;
  364. }
  365. IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target());
  366. ExceptionCode ec = 0;
  367. RefPtr<IDBAny> requestResult = idbRequest->result(ec);
  368. if (ec) {
  369. m_requestCallback->sendFailure("Could not get result in callback.");
  370. return;
  371. }
  372. if (requestResult->type() == IDBAny::ScriptValueType) {
  373. end(false);
  374. return;
  375. }
  376. if (requestResult->type() != IDBAny::IDBCursorWithValueType) {
  377. m_requestCallback->sendFailure("Unexpected result type.");
  378. return;
  379. }
  380. RefPtr<IDBCursorWithValue> idbCursor = requestResult->idbCursorWithValue();
  381. if (m_skipCount) {
  382. ExceptionCode ec = 0;
  383. idbCursor->advance(m_skipCount, ec);
  384. if (ec)
  385. m_requestCallback->sendFailure("Could not advance cursor.");
  386. m_skipCount = 0;
  387. return;
  388. }
  389. if (m_result->length() == m_pageSize) {
  390. end(true);
  391. return;
  392. }
  393. // Continue cursor before making injected script calls, otherwise transaction might be finished.
  394. idbCursor->continueFunction(0, ec);
  395. if (ec) {
  396. m_requestCallback->sendFailure("Could not continue cursor.");
  397. return;
  398. }
  399. RefPtr<DataEntry> dataEntry = DataEntry::create()
  400. .setKey(m_injectedScript.wrapObject(idbCursor->key(), String()))
  401. .setPrimaryKey(m_injectedScript.wrapObject(idbCursor->primaryKey(), String()))
  402. .setValue(m_injectedScript.wrapObject(idbCursor->value(), String()));
  403. m_result->addItem(dataEntry);
  404. }
  405. void end(bool hasMore)
  406. {
  407. if (!m_requestCallback->isActive())
  408. return;
  409. m_requestCallback->sendSuccess(m_result.release(), hasMore);
  410. }
  411. private:
  412. OpenCursorCallback(InjectedScript injectedScript, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize)
  413. : EventListener(EventListener::CPPEventListenerType)
  414. , m_injectedScript(injectedScript)
  415. , m_requestCallback(requestCallback)
  416. , m_skipCount(skipCount)
  417. , m_pageSize(pageSize)
  418. {
  419. m_result = Array<DataEntry>::create();
  420. }
  421. InjectedScript m_injectedScript;
  422. RefPtr<RequestDataCallback> m_requestCallback;
  423. int m_skipCount;
  424. unsigned m_pageSize;
  425. RefPtr<Array<DataEntry> > m_result;
  426. };
  427. class DataLoader : public ExecutableWithDatabase {
  428. public:
  429. static PassRefPtr<DataLoader> create(ScriptExecutionContext* context, PassRefPtr<RequestDataCallback> requestCallback, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize)
  430. {
  431. return adoptRef(new DataLoader(context, requestCallback, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize));
  432. }
  433. virtual ~DataLoader() { }
  434. virtual void execute(PassRefPtr<IDBDatabase> prpDatabase)
  435. {
  436. RefPtr<IDBDatabase> idbDatabase = prpDatabase;
  437. if (!requestCallback()->isActive())
  438. return;
  439. RefPtr<IDBTransaction> idbTransaction = transactionForDatabase(context(), idbDatabase.get(), m_objectStoreName);
  440. if (!idbTransaction) {
  441. m_requestCallback->sendFailure("Could not get transaction");
  442. return;
  443. }
  444. RefPtr<IDBObjectStore> idbObjectStore = objectStoreForTransaction(idbTransaction.get(), m_objectStoreName);
  445. if (!idbObjectStore) {
  446. m_requestCallback->sendFailure("Could not get object store");
  447. return;
  448. }
  449. RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_injectedScript, m_requestCallback, m_skipCount, m_pageSize);
  450. ExceptionCode ec = 0;
  451. RefPtr<IDBRequest> idbRequest;
  452. if (!m_indexName.isEmpty()) {
  453. RefPtr<IDBIndex> idbIndex = indexForObjectStore(idbObjectStore.get(), m_indexName);
  454. if (!idbIndex) {
  455. m_requestCallback->sendFailure("Could not get index");
  456. return;
  457. }
  458. idbRequest = idbIndex->openCursor(context(), PassRefPtr<IDBKeyRange>(m_idbKeyRange), ec);
  459. } else
  460. idbRequest = idbObjectStore->openCursor(context(), PassRefPtr<IDBKeyRange>(m_idbKeyRange), ec);
  461. idbRequest->addEventListener(eventNames().successEvent, openCursorCallback, false);
  462. }
  463. virtual RequestCallback* requestCallback() { return m_requestCallback.get(); }
  464. DataLoader(ScriptExecutionContext* scriptExecutionContext, PassRefPtr<RequestDataCallback> requestCallback, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize)
  465. : ExecutableWithDatabase(scriptExecutionContext)
  466. , m_requestCallback(requestCallback)
  467. , m_injectedScript(injectedScript)
  468. , m_objectStoreName(objectStoreName)
  469. , m_indexName(indexName)
  470. , m_idbKeyRange(idbKeyRange)
  471. , m_skipCount(skipCount)
  472. , m_pageSize(pageSize) { }
  473. RefPtr<RequestDataCallback> m_requestCallback;
  474. InjectedScript m_injectedScript;
  475. String m_objectStoreName;
  476. String m_indexName;
  477. RefPtr<IDBKeyRange> m_idbKeyRange;
  478. int m_skipCount;
  479. unsigned m_pageSize;
  480. };
  481. } // namespace
  482. InspectorIndexedDBAgent::InspectorIndexedDBAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, InspectorPageAgent* pageAgent)
  483. : InspectorBaseAgent<InspectorIndexedDBAgent>("IndexedDB", instrumentingAgents, state)
  484. , m_injectedScriptManager(injectedScriptManager)
  485. , m_pageAgent(pageAgent)
  486. {
  487. }
  488. InspectorIndexedDBAgent::~InspectorIndexedDBAgent()
  489. {
  490. }
  491. void InspectorIndexedDBAgent::clearFrontend()
  492. {
  493. disable(0);
  494. }
  495. void InspectorIndexedDBAgent::restore()
  496. {
  497. if (m_state->getBoolean(IndexedDBAgentState::indexedDBAgentEnabled)) {
  498. ErrorString error;
  499. enable(&error);
  500. }
  501. }
  502. void InspectorIndexedDBAgent::enable(ErrorString*)
  503. {
  504. m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, true);
  505. }
  506. void InspectorIndexedDBAgent::disable(ErrorString*)
  507. {
  508. m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, false);
  509. }
  510. static Document* assertDocument(ErrorString* errorString, Frame* frame)
  511. {
  512. Document* document = frame ? frame->document() : 0;
  513. if (!document)
  514. *errorString = "No document for given frame found";
  515. return document;
  516. }
  517. static IDBFactory* assertIDBFactory(ErrorString* errorString, Document* document)
  518. {
  519. DOMWindow* domWindow = document->domWindow();
  520. if (!domWindow) {
  521. *errorString = "No IndexedDB factory for given frame found";
  522. return 0;
  523. }
  524. IDBFactory* idbFactory = DOMWindowIndexedDatabase::indexedDB(domWindow);
  525. if (!idbFactory)
  526. *errorString = "No IndexedDB factory for given frame found";
  527. return idbFactory;
  528. }
  529. void InspectorIndexedDBAgent::requestDatabaseNames(ErrorString* errorString, const String& securityOrigin, PassRefPtr<RequestDatabaseNamesCallback> requestCallback)
  530. {
  531. Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
  532. Document* document = assertDocument(errorString, frame);
  533. if (!document)
  534. return;
  535. IDBFactory* idbFactory = assertIDBFactory(errorString, document);
  536. if (!idbFactory)
  537. return;
  538. ExceptionCode ec = 0;
  539. RefPtr<IDBRequest> idbRequest = idbFactory->getDatabaseNames(document, ec);
  540. if (ec) {
  541. requestCallback->sendFailure("Could not obtain database names.");
  542. return;
  543. }
  544. idbRequest->addEventListener(eventNames().successEvent, GetDatabaseNamesCallback::create(requestCallback, document->securityOrigin()->toRawString()), false);
  545. }
  546. void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, const String& securityOrigin, const String& databaseName, PassRefPtr<RequestDatabaseCallback> requestCallback)
  547. {
  548. Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
  549. Document* document = assertDocument(errorString, frame);
  550. if (!document)
  551. return;
  552. IDBFactory* idbFactory = assertIDBFactory(errorString, document);
  553. if (!idbFactory)
  554. return;
  555. RefPtr<DatabaseLoader> databaseLoader = DatabaseLoader::create(document, requestCallback);
  556. databaseLoader->start(idbFactory, document->securityOrigin(), databaseName);
  557. }
  558. void InspectorIndexedDBAgent::requestData(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange, PassRefPtr<RequestDataCallback> requestCallback)
  559. {
  560. Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
  561. Document* document = assertDocument(errorString, frame);
  562. if (!document)
  563. return;
  564. IDBFactory* idbFactory = assertIDBFactory(errorString, document);
  565. if (!idbFactory)
  566. return;
  567. InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
  568. RefPtr<IDBKeyRange> idbKeyRange = keyRange ? idbKeyRangeFromKeyRange(keyRange->get()) : 0;
  569. if (keyRange && !idbKeyRange) {
  570. *errorString = "Can not parse key range.";
  571. return;
  572. }
  573. RefPtr<DataLoader> dataLoader = DataLoader::create(document, requestCallback, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize);
  574. dataLoader->start(idbFactory, document->securityOrigin(), databaseName);
  575. }
  576. class ClearObjectStoreListener : public EventListener {
  577. WTF_MAKE_NONCOPYABLE(ClearObjectStoreListener);
  578. public:
  579. static PassRefPtr<ClearObjectStoreListener> create(PassRefPtr<ClearObjectStoreCallback> requestCallback)
  580. {
  581. return adoptRef(new ClearObjectStoreListener(requestCallback));
  582. }
  583. virtual ~ClearObjectStoreListener() { }
  584. virtual bool operator==(const EventListener& other) OVERRIDE
  585. {
  586. return this == &other;
  587. }
  588. virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
  589. {
  590. if (!m_requestCallback->isActive())
  591. return;
  592. if (event->type() != eventNames().completeEvent) {
  593. m_requestCallback->sendFailure("Unexpected event type.");
  594. return;
  595. }
  596. m_requestCallback->sendSuccess();
  597. }
  598. private:
  599. ClearObjectStoreListener(PassRefPtr<ClearObjectStoreCallback> requestCallback)
  600. : EventListener(EventListener::CPPEventListenerType)
  601. , m_requestCallback(requestCallback)
  602. {
  603. }
  604. RefPtr<ClearObjectStoreCallback> m_requestCallback;
  605. };
  606. class ClearObjectStore : public ExecutableWithDatabase {
  607. public:
  608. static PassRefPtr<ClearObjectStore> create(ScriptExecutionContext* context, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
  609. {
  610. return adoptRef(new ClearObjectStore(context, objectStoreName, requestCallback));
  611. }
  612. ClearObjectStore(ScriptExecutionContext* context, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
  613. : ExecutableWithDatabase(context)
  614. , m_objectStoreName(objectStoreName)
  615. , m_requestCallback(requestCallback)
  616. {
  617. }
  618. virtual void execute(PassRefPtr<IDBDatabase> prpDatabase)
  619. {
  620. RefPtr<IDBDatabase> idbDatabase = prpDatabase;
  621. if (!requestCallback()->isActive())
  622. return;
  623. RefPtr<IDBTransaction> idbTransaction = transactionForDatabase(context(), idbDatabase.get(), m_objectStoreName, IDBTransaction::modeReadWrite());
  624. if (!idbTransaction) {
  625. m_requestCallback->sendFailure("Could not get transaction");
  626. return;
  627. }
  628. RefPtr<IDBObjectStore> idbObjectStore = objectStoreForTransaction(idbTransaction.get(), m_objectStoreName);
  629. if (!idbObjectStore) {
  630. m_requestCallback->sendFailure("Could not get object store");
  631. return;
  632. }
  633. ExceptionCode ec = 0;
  634. RefPtr<IDBRequest> idbRequest = idbObjectStore->clear(context(), ec);
  635. ASSERT(!ec);
  636. if (ec) {
  637. m_requestCallback->sendFailure(String::format("Could not clear object store '%s': %d", m_objectStoreName.utf8().data(), ec));
  638. return;
  639. }
  640. idbTransaction->addEventListener(eventNames().completeEvent, ClearObjectStoreListener::create(m_requestCallback), false);
  641. }
  642. virtual RequestCallback* requestCallback() { return m_requestCallback.get(); }
  643. private:
  644. const String m_objectStoreName;
  645. RefPtr<ClearObjectStoreCallback> m_requestCallback;
  646. };
  647. void InspectorIndexedDBAgent::clearObjectStore(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
  648. {
  649. Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
  650. Document* document = assertDocument(errorString, frame);
  651. if (!document)
  652. return;
  653. IDBFactory* idbFactory = assertIDBFactory(errorString, document);
  654. if (!idbFactory)
  655. return;
  656. RefPtr<ClearObjectStore> clearObjectStore = ClearObjectStore::create(document, objectStoreName, requestCallback);
  657. clearObjectStore->start(idbFactory, document->securityOrigin(), databaseName);
  658. }
  659. } // namespace WebCore
  660. #endif // ENABLE(INSPECTOR) && ENABLE(INDEXED_DATABASE)