diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/in_process_webkit/indexed_db_browsertest.cc | 5 | ||||
-rw-r--r-- | content/common/indexed_db/indexed_db_dispatcher.cc | 14 | ||||
-rw-r--r-- | content/common/indexed_db/indexed_db_dispatcher.h | 8 | ||||
-rw-r--r-- | content/common/indexed_db/indexed_db_dispatcher_unittest.cc | 54 | ||||
-rw-r--r-- | content/content_tests.gypi | 1 | ||||
-rw-r--r-- | content/test/data/indexeddb/value_size_test.html | 10 | ||||
-rw-r--r-- | content/test/data/indexeddb/value_size_test.js | 155 |
7 files changed, 245 insertions, 2 deletions
diff --git a/content/browser/in_process_webkit/indexed_db_browsertest.cc b/content/browser/in_process_webkit/indexed_db_browsertest.cc index 510d928..93fc22d 100644 --- a/content/browser/in_process_webkit/indexed_db_browsertest.cc +++ b/content/browser/in_process_webkit/indexed_db_browsertest.cc @@ -107,6 +107,11 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionTest) { SimpleTest(GetTestURL(FilePath(FILE_PATH_LITERAL("transaction_test.html")))); } +// Appears flaky/slow, see: http://crbug.com/120298 +IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_ValueSizeTest) { + SimpleTest(GetTestURL(FilePath(FILE_PATH_LITERAL("value_size_test.html")))); +} + IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DoesntHangTest) { SimpleTest(GetTestURL(FilePath( FILE_PATH_LITERAL("transaction_run_forever.html")))); diff --git a/content/common/indexed_db/indexed_db_dispatcher.cc b/content/common/indexed_db/indexed_db_dispatcher.cc index 827fd94..b778ca2 100644 --- a/content/common/indexed_db/indexed_db_dispatcher.cc +++ b/content/common/indexed_db/indexed_db_dispatcher.cc @@ -17,6 +17,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseCallbacks.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseError.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseException.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyRange.h" using base::ThreadLocalPointer; @@ -43,6 +44,8 @@ int32 CurrentWorkerId() { } // unnamed namespace +const size_t kMaxIDBValueSizeInBytes = 64 * 1024 * 1024; + IndexedDBDispatcher::IndexedDBDispatcher() { g_idb_dispatcher_tls.Pointer()->Set(this); } @@ -113,7 +116,11 @@ void IndexedDBDispatcher::RequestIDBCursorUpdate( WebExceptionCode* ec) { ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); - + if (!value.is_null() && + (value.data().length() * sizeof(char16)) > kMaxIDBValueSizeInBytes) { + *ec = WebKit::WebIDBDatabaseExceptionDataError; + return; + } int32 response_id = pending_callbacks_.Add(callbacks.release()); Send( new IndexedDBHostMsg_CursorUpdate(idb_cursor_id, CurrentWorkerId(), @@ -398,6 +405,11 @@ void IndexedDBDispatcher::RequestIDBObjectStorePut( WebExceptionCode* ec) { ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + if (!value.is_null() && + (value.data().length() * sizeof(char16)) > kMaxIDBValueSizeInBytes) { + *ec = WebKit::WebIDBDatabaseExceptionDataError; + return; + } IndexedDBHostMsg_ObjectStorePut_Params params; params.thread_id = CurrentWorkerId(); params.idb_object_store_id = idb_object_store_id; diff --git a/content/common/indexed_db/indexed_db_dispatcher.h b/content/common/indexed_db/indexed_db_dispatcher.h index f4b0b4b..f48e7c2 100644 --- a/content/common/indexed_db/indexed_db_dispatcher.h +++ b/content/common/indexed_db/indexed_db_dispatcher.h @@ -11,6 +11,7 @@ #include "base/id_map.h" #include "base/nullable_string16.h" +#include "content/common/content_export.h" #include "ipc/ipc_sync_message_filter.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCallbacks.h" @@ -41,9 +42,12 @@ namespace content { class SerializedScriptValue; } +CONTENT_EXPORT extern const size_t kMaxIDBValueSizeInBytes; + // Handle the indexed db related communication for this context thread - the // main thread and each worker thread have their own copies. -class IndexedDBDispatcher : public webkit_glue::WorkerTaskRunner::Observer { +class CONTENT_EXPORT IndexedDBDispatcher + : public webkit_glue::WorkerTaskRunner::Observer { public: virtual ~IndexedDBDispatcher(); static IndexedDBDispatcher* ThreadSpecificInstance(); @@ -203,6 +207,8 @@ class IndexedDBDispatcher : public webkit_glue::WorkerTaskRunner::Observer { static int32 TransactionId(const WebKit::WebIDBTransaction& transaction); private: + FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, ValueSizeTest); + IndexedDBDispatcher(); // IDBCallback message handlers. void OnSuccessNull(int32 response_id); diff --git a/content/common/indexed_db/indexed_db_dispatcher_unittest.cc b/content/common/indexed_db/indexed_db_dispatcher_unittest.cc new file mode 100644 index 0000000..ea4dbaf --- /dev/null +++ b/content/common/indexed_db/indexed_db_dispatcher_unittest.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "content/common/indexed_db/indexed_db_dispatcher.h" +#include "content/common/indexed_db/indexed_db_key.h" +#include "content/public/common/serialized_script_value.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCallbacks.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBTransaction.h" + +class FakeWebIDBTransaction : public WebKit::WebIDBTransaction { + public: + FakeWebIDBTransaction() {} +}; + +TEST(IndexedDBDispatcherTest, ValueSizeTest) { + string16 data; + data.resize(kMaxIDBValueSizeInBytes / sizeof(char16) + 1, 'x'); + const bool kIsNull = false; + const bool kIsInvalid = false; + const content::SerializedScriptValue value(kIsNull, kIsInvalid, data); + const int32 dummy_id = -1; + + { + IndexedDBDispatcher dispatcher; + IndexedDBKey key; + key.SetNumber(0); + WebKit::WebExceptionCode ec = 0; + dispatcher.RequestIDBObjectStorePut( + value, + key, + WebKit::WebIDBObjectStore::AddOrUpdate, + static_cast<WebKit::WebIDBCallbacks*>(NULL), + dummy_id, + FakeWebIDBTransaction(), + &ec); + EXPECT_NE(ec, 0); + } + + { + IndexedDBDispatcher dispatcher; + WebKit::WebExceptionCode ec = 0; + dispatcher.RequestIDBCursorUpdate( + value, + static_cast<WebKit::WebIDBCallbacks*>(NULL), + dummy_id, + &ec); + EXPECT_NE(ec, 0); + } +} diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 44ef508..1befa63 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -268,6 +268,7 @@ 'common/gpu/gpu_info_unittest.cc', 'common/gpu/gpu_memory_manager_unittest.cc', 'common/hi_res_timer_manager_unittest.cc', + 'common/indexed_db/indexed_db_dispatcher_unittest.cc', 'common/inter_process_time_ticks_converter_unittest.cc', 'common/net/url_fetcher_impl_unittest.cc', 'common/page_zoom_unittest.cc', diff --git a/content/test/data/indexeddb/value_size_test.html b/content/test/data/indexeddb/value_size_test.html new file mode 100644 index 0000000..33988ed --- /dev/null +++ b/content/test/data/indexeddb/value_size_test.html @@ -0,0 +1,10 @@ +<html> + <head> + <title>IndexedDB value size test</title> + <script type="text/javascript" src="common.js"></script> + <script type="text/javascript" src="value_size_test.js"></script> + </head> + <body onLoad="test()"> + <div id="status">Starting...</div> + </body> +</html> diff --git a/content/test/data/indexeddb/value_size_test.js b/content/test/data/indexeddb/value_size_test.js new file mode 100644 index 0000000..17948120 --- /dev/null +++ b/content/test/data/indexeddb/value_size_test.js @@ -0,0 +1,155 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function test() +{ + if ('webkitIndexedDB' in window) { + indexedDB = webkitIndexedDB; + IDBTransaction = webkitIDBTransaction; + IDBDatabaseException = webkitIDBDatabaseException; + } + + debug('Deleting previous database'); + var DBNAME = 'value-size', VERSION = 1; + var request = indexedDB.deleteDatabase(DBNAME); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + debug('Opening database connection'); + request = indexedDB.open(DBNAME); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + db = request.result; + debug('Setting version'); + request = db.setVersion(VERSION); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + debug('Creating object store'); + var store = db.createObjectStore('store'); + store.put("FIRST!!!111!", -Infinity); + var transaction = request.result; + transaction.oncomplete = function () { + setTimeout(testUnderLimit, 0); + }; + }; + }; + }; +} + +function repeat(string, len) +{ + return Array(len + 1).join(string); +} + +var SEED = "\u0100"; // Encodes to 2 byte in UTF-8 and UTF-16 +var BYTES_PER_CHAR = 2; +var CHARS_PER_MB = 1024 * 1024 / BYTES_PER_CHAR; +var SLOP = 1024; +var LIMIT_MB = 64; +var key = 0; +var value; + +function testUnderLimit() +{ + debug('Creating test value under limit'); + var underLimit; + setTimeout( + function () { + value = repeat(SEED, LIMIT_MB * CHARS_PER_MB - SLOP); // Just under limit + underLimit = value; + setTimeout(doStore, 0); + }, 0); + + function doStore() { + var transaction = db.transaction("store", IDBTransaction.READ_WRITE); + var store = transaction.objectStore("store"); + var request; + + debug("store.add underLimit"); + request = store.add(underLimit, key++); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + debug("store.add succeeded"); + debug("store.put underLimit"); + request = store.put(underLimit, key++); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + debug("store.put succeeded"); + request = store.openCursor(); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + var cursor = request.result; + debug("cursor.update underLimit"); + request = cursor.update(underLimit); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + debug("cursor.update succeeded"); + transaction.abort(); + }; + }; + }; + }; + + transaction.oncomplete = unexpectedCompleteCallback; + transaction.onabort = testOverLimit; + } +} + +function testOverLimit() +{ + debug('Creating test value over limit'); + var overLimit; + setTimeout( + function () { + overLimit = value + repeat(SEED, SLOP * 2); + setTimeout(doStore, 0); + }, 0); + + function doStore() { + var transaction = db.transaction("store", IDBTransaction.READ_WRITE); + var store = transaction.objectStore("store"); + var request; + try { + debug("store.add overLimit"); + request = store.add(overLimit, key++); + request.onsuccess = unexpectedSuccessCallback; + fail('store.add - Expected exception, but none was raised'); + } catch (e) { + debug('Exception (expected)'); + code = e.code; + shouldBe("code", "IDBDatabaseException.DATA_ERR"); + } + + try { + debug("store.put overLimit"); + request = store.put(overLimit, key++); + request.onsuccess = unexpectedSuccessCallback; + fail('store.add - Expected exception, but none was raised'); + } catch (e) { + debug('Exception (expected)'); + code = e.code; + shouldBe("code", "IDBDatabaseException.DATA_ERR"); + } + + request = store.openCursor(); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function () { + var cursor = request.result; + try { + debug("cursor.update overLimit"); + request = cursor.update(overLimit); + request.onerror = unexpectedSuccessCallback; + fail('cursor.update - Expected exception, but none was raised'); + } catch (e) { + debug('Exception (expected)'); + code = e.code; + shouldBe("code", "IDBDatabaseException.DATA_ERR"); + + transaction.abort(); + } + }; + + transaction.oncomplete = unexpectedCompleteCallback; + transaction.onabort = function() { done(); }; + } +} |