summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
Diffstat (limited to 'content')
-rw-r--r--content/browser/in_process_webkit/indexed_db_browsertest.cc5
-rw-r--r--content/common/indexed_db/indexed_db_dispatcher.cc14
-rw-r--r--content/common/indexed_db/indexed_db_dispatcher.h8
-rw-r--r--content/common/indexed_db/indexed_db_dispatcher_unittest.cc54
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/test/data/indexeddb/value_size_test.html10
-rw-r--r--content/test/data/indexeddb/value_size_test.js155
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(); };
+ }
+}