Bug 772700 - 'IndexedDB - OOP from a JS component or JSM doesn't work'. r=khuey+mrbkap.

--HG--
rename : dom/indexedDB/test/unit/head_idb.js => dom/indexedDB/test/unit/head.js
extra : transplant_source : %5D1%15%CC%90%E0%F5%0D%0B%FDi%0B%B9YA%D4c%24%D42
This commit is contained in:
Ben Turner 2012-07-14 07:24:20 -04:00
parent b547035544
commit f44ed8784a
17 changed files with 307 additions and 22 deletions

View File

@ -9,9 +9,16 @@
#include "IDBFactory.h"
#include "nsIFile.h"
#include "nsIJSContextStack.h"
#include "nsIPrincipal.h"
#include "nsIScriptContext.h"
#include "nsIXPConnect.h"
#include "nsIXPCScriptable.h"
#include "jsdbgapi.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/storage.h"
#include "nsComponentManagerUtils.h"
#include "nsIScriptSecurityManager.h"
@ -34,14 +41,13 @@
#include "IndexedDatabaseManager.h"
#include "Key.h"
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/dom/TabChild.h"
using mozilla::dom::TabChild;
#include "ipc/IndexedDBChild.h"
USING_INDEXEDDB_NAMESPACE
using mozilla::dom::ContentChild;
using mozilla::dom::TabChild;
namespace {
struct ObjectStoreInfoMap
@ -56,7 +62,8 @@ struct ObjectStoreInfoMap
} // anonymous namespace
IDBFactory::IDBFactory()
: mOwningObject(nsnull), mActorChild(nsnull), mActorParent(nsnull)
: mOwningObject(nsnull), mActorChild(nsnull), mActorParent(nsnull),
mRootedOwningObject(false)
{
}
@ -68,6 +75,9 @@ IDBFactory::~IDBFactory()
mActorChild->Send__delete__(mActorChild);
NS_ASSERTION(!mActorChild, "Should have cleared in Send__delete__!");
}
if (mRootedOwningObject) {
NS_DROP_JS_OBJECTS(this, IDBFactory);
}
}
// static
@ -153,6 +163,92 @@ IDBFactory::Create(JSContext* aCx,
factory->mASCIIOrigin = origin;
factory->mOwningObject = aOwningObject;
if (!IndexedDatabaseManager::IsMainProcess()) {
ContentChild* contentChild = ContentChild::GetSingleton();
NS_ENSURE_TRUE(contentChild, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
IndexedDBChild* actor = new IndexedDBChild(origin);
contentChild->SendPIndexedDBConstructor(actor);
actor->SetFactory(factory);
}
factory.forget(aFactory);
return NS_OK;
}
// static
nsresult
IDBFactory::Create(IDBFactory** aFactory)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
#ifdef DEBUG
{
nsIThreadJSContextStack* cxStack = nsContentUtils::ThreadJSContextStack();
NS_ASSERTION(cxStack, "Couldn't get ThreadJSContextStack!");
JSContext* lastCx;
if (NS_SUCCEEDED(cxStack->Peek(&lastCx))) {
NS_ASSERTION(!lastCx, "We should only be called from C++!");
}
else {
NS_ERROR("nsIThreadJSContextStack::Peek should never fail!");
}
}
#endif
nsCString origin;
nsresult rv =
IndexedDatabaseManager::GetASCIIOriginFromWindow(nsnull, origin);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principal =
do_CreateInstance("@mozilla.org/nullprincipal;1");
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
JSContext* cx = nsContentUtils::GetSafeJSContext();
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
nsCxPusher pusher;
if (!pusher.Push(cx)) {
NS_WARNING("Failed to push safe JS context!");
return NS_ERROR_FAILURE;
}
JSAutoRequest ar(cx);
nsIXPConnect* xpc = nsContentUtils::XPConnect();
NS_ASSERTION(xpc, "This should never be null!");
nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
NS_ENSURE_SUCCESS(rv, rv);
JSObject* global;
rv = globalHolder->GetJSObject(&global);
NS_ENSURE_SUCCESS(rv, rv);
// The CreateSandbox call returns a proxy to the actual sandbox object. We
// don't need a proxy here.
global = JS_UnwrapObject(global);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, global)) {
NS_WARNING("Failed to enter compartment!");
return NS_ERROR_FAILURE;
}
nsRefPtr<IDBFactory> factory;
rv = Create(cx, global, getter_AddRefs(factory));
NS_ENSURE_SUCCESS(rv, rv);
NS_HOLD_JS_OBJECTS(factory, IDBFactory);
factory->mRootedOwningObject = true;
factory.forget(aFactory);
return NS_OK;
}
@ -389,6 +485,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBFactory)
if (tmp->mOwningObject) {
tmp->mOwningObject = nsnull;
}
if (tmp->mRootedOwningObject) {
NS_DROP_JS_OBJECTS(tmp, IDBFactory);
tmp->mRootedOwningObject = false;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

View File

@ -36,10 +36,12 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
NS_DECL_NSIIDBFACTORY
// Called when using IndexedDB from a window in a different process.
static nsresult Create(nsPIDOMWindow* aWindow,
const nsACString& aASCIIOrigin,
IDBFactory** aFactory);
// Called when using IndexedDB from a window in the current process.
static nsresult Create(nsPIDOMWindow* aWindow,
nsIIDBFactory** aFactory)
{
@ -51,10 +53,16 @@ public:
return NS_OK;
}
// Called when using IndexedDB from a JS component or a JSM in the current
// process.
static nsresult Create(JSContext* aCx,
JSObject* aOwningObject,
IDBFactory** aFactory);
// Called when using IndexedDB from a JS component or a JSM in a different
// process.
static nsresult Create(IDBFactory** aFactory);
static already_AddRefed<mozIStorageConnection>
GetConnection(const nsAString& aDatabaseFilePath);
@ -90,6 +98,12 @@ public:
mActorParent = aActorParent;
}
const nsCString&
GetASCIIOrigin() const
{
return mASCIIOrigin;
}
private:
IDBFactory();
~IDBFactory();
@ -103,6 +117,8 @@ private:
IndexedDBChild* mActorChild;
IndexedDBParent* mActorParent;
bool mRootedOwningObject;
};
END_INDEXEDDB_NAMESPACE

View File

@ -22,6 +22,7 @@
namespace mozilla {
namespace dom {
class ContentParent;
class TabParent;
}
}
@ -129,6 +130,7 @@ public:
class IndexedDBParent : public PIndexedDBParent
{
friend class mozilla::dom::ContentParent;
friend class mozilla::dom::TabParent;
nsRefPtr<IDBFactory> mFactory;

View File

@ -31,10 +31,20 @@ LOCAL_INCLUDES += \
DEFINES += -D_IMPL_NS_LAYOUT
MOCHITEST_FILES = \
test_ipc.html \
$(NULL)
MOCHITEST_FILES = test_ipc.html
XPCSHELL_TESTS = unit
# We're copying tests from another directory so this check is wrong for us.
NO_XPCSHELL_MANIFEST_CHECK = 1
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
# Copy all the normal xpcshell tests from the regular unit directory.
copy-xpcshell-tests:
$(DIR_INSTALL) $(wildcard $(topsrcdir)/dom/indexedDB/test/unit/test_*.js) \
$(testxpcobjdir)/$(relativesrcdir)/$(XPCSHELL_TESTS)
libs-xpcshell-tests: copy-xpcshell-tests

View File

@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBrowser;
include protocol PContent;
include protocol PIndexedDBDatabase;
include protocol PIndexedDBDeleteDatabaseRequest;
@ -12,7 +13,7 @@ namespace indexedDB {
protocol PIndexedDB
{
manager PBrowser;
manager PBrowser or PContent;
manages PIndexedDBDatabase;
manages PIndexedDBDeleteDatabaseRequest;

View File

@ -0,0 +1,18 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const INDEXEDDB_UNIT_DIR = "../../test/unit/";
const INDEXEDDB_HEAD_FILE = INDEXEDDB_UNIT_DIR + "head.js";
function run_test() {
// IndexedDB needs a profile.
do_get_profile();
let thisTest = _TEST_FILE.toString().replace(/\\/g, "/");
thisTest = thisTest.substring(thisTest.lastIndexOf("/") + 1);
_HEAD_FILES.push(do_get_file(INDEXEDDB_HEAD_FILE).path.replace(/\\/g, "/"));
run_test_in_child(INDEXEDDB_UNIT_DIR + thisTest);
}

View File

@ -0,0 +1,60 @@
[DEFAULT]
head = head.js
tail =
# When adding files here please also update test/unit/xpcshell.ini!
[test_add_put.js]
[test_add_twice_failure.js]
[test_advance.js]
[test_autoIncrement_indexes.js]
[test_clear.js]
[test_complex_keyPaths.js]
[test_count.js]
[test_create_index.js]
[test_create_index_with_integer_keys.js]
[test_create_objectStore.js]
[test_cursor_mutation.js]
[test_cursor_update_updates_indexes.js]
[test_cursors.js]
[test_deleteDatabase.js]
[test_event_source.js]
[test_getAll.js]
[test_global_data.js]
[test_index_empty_keyPath.js]
[test_index_getAll.js]
[test_index_getAllObjects.js]
[test_index_object_cursors.js]
[test_index_update_delete.js]
[test_indexes.js]
[test_indexes_bad_values.js]
[test_key_requirements.js]
[test_keys.js]
[test_multientry.js]
[test_names_sorted.js]
[test_object_identity.js]
[test_objectCursors.js]
[test_objectStore_inline_autoincrement_key_added_on_put.js]
[test_objectStore_remove_values.js]
[test_odd_result_order.js]
[test_open_empty_db.js]
[test_open_objectStore.js]
[test_optionalArguments.js]
[test_overlapping_transactions.js]
[test_put_get_values.js]
[test_put_get_values_autoIncrement.js]
[test_remove_index.js]
[test_remove_objectStore.js]
[test_request_readyState.js]
[test_setVersion.js]
[test_setVersion_abort.js]
[test_setVersion_events.js]
[test_setVersion_exclusion.js]
[test_success_events_after_abort.js]
[test_traffic_jam.js]
[test_transaction_abort.js]
[test_transaction_lifetimes.js]
[test_transaction_lifetimes_nested.js]
[test_transaction_ordering.js]
# When adding files here please also update test/unit/xpcshell.ini!

View File

@ -7,10 +7,11 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/indexedDB/test
DIRS += unit
include $(DEPTH)/config/autoconf.mk
TEST_DIRS = unit
XPCSHELL_TESTS = unit
MOCHITEST_FILES = \
@ -125,4 +126,3 @@ MOCHITEST_BROWSER_FILES = \
endif
include $(topsrcdir)/config/rules.mk

View File

@ -16,13 +16,6 @@ const IDBIndex = Ci.nsIIDBIndex
const IDBObjectStore = Ci.nsIIDBObjectStore
const IDBRequest = Ci.nsIIDBRequest
// XPCShell does not get a profile by default.
do_get_profile();
var idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"].
getService(Ci.nsIIndexedDatabaseManager);
idbManager.initWindowless(this);
function is(a, b, msg) {
dump("is(" + a + ", " + b + ", \"" + msg + "\")");
do_check_eq(a, b, Components.stack.caller);
@ -52,6 +45,13 @@ function run_test() {
function runTest()
{
// XPCShell does not get a profile by default.
do_get_profile();
var idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"].
getService(Ci.nsIIndexedDatabaseManager);
idbManager.initWindowless(this);
do_test_pending();
testGenerator.next();
}

View File

@ -1,6 +1,8 @@
[DEFAULT]
head = head_idb.js
tail =
head = head.js
tail =
# When adding files here please also update ipc/unit/xpcshell.ini!
[test_add_put.js]
[test_add_twice_failure.js]
@ -53,4 +55,6 @@ tail =
[test_transaction_abort.js]
[test_transaction_lifetimes.js]
[test_transaction_lifetimes_nested.js]
[test_transaction_ordering.js]
[test_transaction_ordering.js]
# When adding files here please also update ipc/unit/xpcshell.ini!

View File

@ -88,6 +88,7 @@ using namespace mozilla::places;
using namespace mozilla::docshell;
using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::sms;
using namespace mozilla::dom::indexedDB;
namespace mozilla {
namespace dom {
@ -429,6 +430,20 @@ ContentChild::DeallocPHal(PHalChild* aHal)
return true;
}
PIndexedDBChild*
ContentChild::AllocPIndexedDB()
{
NS_NOTREACHED("Should never get here!");
return NULL;
}
bool
ContentChild::DeallocPIndexedDB(PIndexedDBChild* aActor)
{
delete aActor;
return true;
}
PTestShellChild*
ContentChild::AllocPTestShell()
{

View File

@ -71,6 +71,9 @@ public:
NS_OVERRIDE virtual PHalChild* AllocPHal();
NS_OVERRIDE virtual bool DeallocPHal(PHalChild*);
virtual PIndexedDBChild* AllocPIndexedDB();
virtual bool DeallocPIndexedDB(PIndexedDBChild* aActor);
virtual PMemoryReportRequestChild*
AllocPMemoryReportRequest();

View File

@ -83,6 +83,10 @@
#include "nsDirectoryServiceDefs.h"
#include "mozilla/Preferences.h"
#include "IDBFactory.h"
#include "IndexedDatabaseManager.h"
#include "IndexedDBParent.h"
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
@ -95,6 +99,7 @@ using mozilla::unused; // heh
using base::KillProcess;
using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::sms;
using namespace mozilla::dom::indexedDB;
namespace mozilla {
namespace dom {
@ -829,6 +834,42 @@ ContentParent::DeallocPHal(PHalParent* aHal)
return true;
}
PIndexedDBParent*
ContentParent::AllocPIndexedDB()
{
return new IndexedDBParent();
}
bool
ContentParent::DeallocPIndexedDB(PIndexedDBParent* aActor)
{
delete aActor;
return true;
}
bool
ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor)
{
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
NS_ENSURE_TRUE(mgr, false);
if (!IndexedDatabaseManager::IsMainProcess()) {
NS_RUNTIMEABORT("Not supported yet!");
}
nsRefPtr<IDBFactory> factory;
nsresult rv = IDBFactory::Create(getter_AddRefs(factory));
NS_ENSURE_SUCCESS(rv, false);
NS_ASSERTION(factory, "This should never be null!");
IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor);
actor->mFactory = factory;
actor->mASCIIOrigin = factory->GetASCIIOrigin();
return true;
}
PMemoryReportRequestParent*
ContentParent::AllocPMemoryReportRequest()
{

View File

@ -123,6 +123,13 @@ private:
NS_OVERRIDE virtual PHalParent* AllocPHal();
NS_OVERRIDE virtual bool DeallocPHal(PHalParent*);
virtual PIndexedDBParent* AllocPIndexedDB();
virtual bool DeallocPIndexedDB(PIndexedDBParent* aActor);
virtual bool
RecvPIndexedDBConstructor(PIndexedDBParent* aActor);
virtual PMemoryReportRequestParent* AllocPMemoryReportRequest();
virtual bool DeallocPMemoryReportRequest(PMemoryReportRequestParent* actor);

View File

@ -10,6 +10,7 @@ include protocol PCrashReporter;
include protocol PExternalHelperApp;
include protocol PDeviceStorageRequest;
include protocol PHal;
include protocol PIndexedDB;
include protocol PMemoryReportRequest;
include protocol PNecko;
include protocol PSms;
@ -102,6 +103,7 @@ rpc protocol PContent
manages PDeviceStorageRequest;
manages PExternalHelperApp;
manages PHal;
manages PIndexedDB;
manages PMemoryReportRequest;
manages PNecko;
manages PSms;
@ -167,6 +169,8 @@ parent:
PHal();
PIndexedDB();
PNecko();
PSms();

View File

@ -244,7 +244,7 @@ protected:
virtual PIndexedDBChild* AllocPIndexedDB(const nsCString& aASCIIOrigin,
bool* /* aAllowed */);
virtual bool DeallocPIndexedDB(PIndexedDBChild* actor);
virtual bool DeallocPIndexedDB(PIndexedDBChild* aActor);
private:
void ActorDestroy(ActorDestroyReason why);

View File

@ -128,3 +128,7 @@ run-if.config = ipc
skip-if = os == "android"
[include:tools/profiler/tests/xpcshell.ini]
[include:dom/indexedDB/ipc/unit/xpcshell.ini]
run-if.config = ipc
skip-if.os != "win"