Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
shindli 2018-08-20 19:35:19 +03:00
commit 39fac07af8
69 changed files with 4492 additions and 361 deletions

View file

@ -133,9 +133,6 @@ oddly_ordered_inclnames = set([
# - This script has been broken somehow.
#
expected_output = '''\
js/src/tests/style/BadIncludes2.h:1: error:
vanilla header includes an inline-header file "tests/style/BadIncludes2-inl.h"
js/src/tests/style/BadIncludes.h:3: error:
the file includes itself
@ -151,6 +148,9 @@ js/src/tests/style/BadIncludes.h:10: error:
"stdio.h" is included using the wrong path;
did you forget a prefix, or is the file not yet committed?
js/src/tests/style/BadIncludes2.h:1: error:
vanilla header includes an inline-header file "tests/style/BadIncludes2-inl.h"
js/src/tests/style/BadIncludesOrder-inl.h:5:6: error:
"vm/JSScript-inl.h" should be included after "vm/Interpreter-inl.h"
@ -306,7 +306,7 @@ def check_style(enable_fixup):
edges[inclname] = set()
# Process all the JS files.
for filename in js_names.keys():
for filename in sorted(js_names.keys()):
inclname = js_names[filename]
file_kind = FileKind.get(filename)
if file_kind == FileKind.C or file_kind == FileKind.CPP or \

View file

@ -3496,29 +3496,30 @@ def CreateBindingJSObject(descriptor, properties):
# of cases where we do, so for simplicity, just always root it.
if descriptor.proxy:
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
expandoValue = "JS::PrivateValue(&aObject->mExpandoAndGeneration)"
create = dedent(
"""
MOZ_ASSERT(aObject->mExpandoAndGeneration.expando.isUndefined());
JS::Rooted<JS::Value> expandoValue(aCx, JS::PrivateValue(&aObject->mExpandoAndGeneration));
creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
proto, aObject, expandoValue, aReflector);
""")
else:
expandoValue = "JS::UndefinedValue()"
create = fill(
"""
JS::Rooted<JS::Value> expandoValue(aCx, ${expandoValue});
creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
proto, aObject, expandoValue, aReflector);
if (!aReflector) {
return false;
}
""",
expandoValue=expandoValue)
create = dedent(
"""
creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
proto, aObject, JS::UndefinedHandleValue, aReflector);
""")
else:
create = dedent(
"""
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
""")
return objDecl + create
return objDecl + create + dedent(
"""
if (!aReflector) {
return false;
}
""")
def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode,

View file

@ -69,11 +69,53 @@ struct SetDOMProxyInformation
SetDOMProxyInformation gSetDOMProxyInformation;
static inline void
CheckExpandoObject(JSObject* proxy, const JS::Value& expando)
{
#ifdef DEBUG
JSObject* obj = &expando.toObject();
MOZ_ASSERT(!js::gc::EdgeNeedsSweepUnbarriered(&obj));
MOZ_ASSERT(js::GetObjectCompartment(proxy) == js::GetObjectCompartment(obj));
// When we create an expando object in EnsureExpandoObject below, we preserve
// the wrapper. The wrapper is released when the object is unlinked, but we
// should never call these functions after that point.
nsISupports* native = UnwrapDOMObject<nsISupports>(proxy);
nsWrapperCache* cache;
CallQueryInterface(native, &cache);
MOZ_ASSERT(cache->PreservingWrapper());
#endif
}
static inline void
CheckExpandoAndGeneration(JSObject* proxy, js::ExpandoAndGeneration* expandoAndGeneration)
{
#ifdef DEBUG
JS::Value value = expandoAndGeneration->expando;
if (!value.isUndefined())
CheckExpandoObject(proxy, value);
#endif
}
static inline void
CheckDOMProxy(JSObject* proxy)
{
#ifdef DEBUG
MOZ_ASSERT(IsDOMProxy(proxy), "expected a DOM proxy object");
MOZ_ASSERT(!js::gc::EdgeNeedsSweepUnbarriered(&proxy));
nsISupports* native = UnwrapDOMObject<nsISupports>(proxy);
nsWrapperCache* cache;
CallQueryInterface(native, &cache);
MOZ_ASSERT(cache->GetWrapperPreserveColor() == proxy);
#endif
}
// static
JSObject*
DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj)
{
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
CheckDOMProxy(obj);
JS::Value v = js::GetProxyPrivate(obj);
if (v.isUndefined()) {
return nullptr;
@ -104,6 +146,7 @@ DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj)
expandoAndGeneration->expando = UndefinedValue();
}
CheckExpandoObject(obj, v);
return &v.toObject();
}
@ -112,15 +155,18 @@ DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj)
JSObject*
DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
{
NS_ASSERTION(IsDOMProxy(obj), "expected a DOM proxy object");
CheckDOMProxy(obj);
JS::Value v = js::GetProxyPrivate(obj);
if (v.isObject()) {
CheckExpandoObject(obj, v);
return &v.toObject();
}
js::ExpandoAndGeneration* expandoAndGeneration;
if (!v.isUndefined()) {
expandoAndGeneration = static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
CheckExpandoAndGeneration(obj, expandoAndGeneration);
if (expandoAndGeneration->expando.isObject()) {
return &expandoAndGeneration->expando.toObject();
}
@ -270,9 +316,11 @@ DOMProxyHandler::setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handl
JSObject *
DOMProxyHandler::GetExpandoObject(JSObject *obj)
{
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
CheckDOMProxy(obj);
JS::Value v = js::GetProxyPrivate(obj);
if (v.isObject()) {
CheckExpandoObject(obj, v);
return &v.toObject();
}
@ -282,6 +330,8 @@ DOMProxyHandler::GetExpandoObject(JSObject *obj)
js::ExpandoAndGeneration* expandoAndGeneration =
static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
CheckExpandoAndGeneration(obj, expandoAndGeneration);
v = expandoAndGeneration->expando;
return v.isUndefined() ? nullptr : &v.toObject();
}

View file

@ -184,8 +184,8 @@ BodyStartWriteStream(const QuotaInfo& aQuotaInfo,
if (NS_WARN_IF(exists)) { return NS_ERROR_FILE_ALREADY_EXISTS; }
nsCOMPtr<nsIOutputStream> fileStream =
FileOutputStream::Create(PERSISTENCE_TYPE_DEFAULT, aQuotaInfo.mGroup,
aQuotaInfo.mOrigin, tmpFile);
CreateFileOutputStream(PERSISTENCE_TYPE_DEFAULT, aQuotaInfo.mGroup,
aQuotaInfo.mOrigin, tmpFile);
if (NS_WARN_IF(!fileStream)) { return NS_ERROR_UNEXPECTED; }
RefPtr<SnappyCompressOutputStream> compressed =
@ -263,8 +263,8 @@ BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, const nsID& aId,
if (NS_WARN_IF(!exists)) { return NS_ERROR_FILE_NOT_FOUND; }
nsCOMPtr<nsIInputStream> fileStream =
FileInputStream::Create(PERSISTENCE_TYPE_DEFAULT, aQuotaInfo.mGroup,
aQuotaInfo.mOrigin, finalFile);
CreateFileInputStream(PERSISTENCE_TYPE_DEFAULT, aQuotaInfo.mGroup,
aQuotaInfo.mOrigin, finalFile);
if (NS_WARN_IF(!fileStream)) { return NS_ERROR_UNEXPECTED; }
fileStream.forget(aStreamOut);

View file

@ -17,6 +17,7 @@
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseParent.h"
#include "mozilla/dom/IPCBlobUtils.h"
#include "mozilla/dom/ipc/PendingIPCBlobParent.h"
#include "mozilla/dom/quota/MemoryOutputStream.h"
#include "nsAutoPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsDebug.h"
@ -48,6 +49,7 @@
namespace mozilla {
namespace dom {
using namespace mozilla::dom::quota;
using namespace mozilla::ipc;
namespace {
@ -632,8 +634,6 @@ class ReadOp final
{
friend class FileHandle;
class MemoryOutputStream;
const FileRequestReadParams mParams;
private:
@ -651,34 +651,6 @@ private:
GetResponse(FileRequestResponse& aResponse) override;
};
class ReadOp::MemoryOutputStream final
: public nsIOutputStream
{
nsCString mData;
uint64_t mOffset;
public:
static already_AddRefed<MemoryOutputStream>
Create(uint64_t aSize);
const nsCString&
Data() const
{
return mData;
}
private:
MemoryOutputStream()
: mOffset(0)
{ }
virtual ~MemoryOutputStream()
{ }
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOUTPUTSTREAM
};
class WriteOp final
: public CopyFileHandleOp
{
@ -2404,96 +2376,6 @@ ReadOp::GetResponse(FileRequestResponse& aResponse)
aResponse = FileRequestReadResponse(stream->Data());
}
// static
already_AddRefed<ReadOp::MemoryOutputStream>
ReadOp::
MemoryOutputStream::Create(uint64_t aSize)
{
MOZ_ASSERT(aSize, "Passed zero size!");
if (NS_WARN_IF(aSize > UINT32_MAX)) {
return nullptr;
}
RefPtr<MemoryOutputStream> stream = new MemoryOutputStream();
char* dummy;
uint32_t length = stream->mData.GetMutableData(&dummy, aSize, fallible);
if (NS_WARN_IF(length != aSize)) {
return nullptr;
}
return stream.forget();
}
NS_IMPL_ISUPPORTS(ReadOp::MemoryOutputStream, nsIOutputStream)
NS_IMETHODIMP
ReadOp::
MemoryOutputStream::Close()
{
mData.Truncate(mOffset);
return NS_OK;
}
NS_IMETHODIMP
ReadOp::
MemoryOutputStream::Write(const char* aBuf, uint32_t aCount, uint32_t* _retval)
{
return WriteSegments(NS_CopySegmentToBuffer, (char*)aBuf, aCount, _retval);
}
NS_IMETHODIMP
ReadOp::
MemoryOutputStream::Flush()
{
return NS_OK;
}
NS_IMETHODIMP
ReadOp::
MemoryOutputStream::WriteFrom(nsIInputStream* aFromStream, uint32_t aCount,
uint32_t* _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ReadOp::
MemoryOutputStream::WriteSegments(nsReadSegmentFun aReader, void* aClosure,
uint32_t aCount, uint32_t* _retval)
{
NS_ASSERTION(mData.Length() >= mOffset, "Bad stream state!");
uint32_t maxCount = mData.Length() - mOffset;
if (maxCount == 0) {
*_retval = 0;
return NS_OK;
}
if (aCount > maxCount) {
aCount = maxCount;
}
nsresult rv = aReader(this, aClosure, mData.BeginWriting() + mOffset, 0,
aCount, _retval);
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(*_retval <= aCount,
"Reader should not read more than we asked it to read!");
mOffset += *_retval;
}
return NS_OK;
}
NS_IMETHODIMP
ReadOp::
MemoryOutputStream::IsNonBlocking(bool* _retval)
{
*_retval = false;
return NS_OK;
}
WriteOp::WriteOp(FileHandle* aFileHandle,
const FileRequestParams& aParams)
: CopyFileHandleOp(aFileHandle)

View file

@ -9089,7 +9089,8 @@ public:
nsThreadPool*
GetOrCreateThreadPool();
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(QuotaClient, override)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(
mozilla::dom::indexedDB::QuotaClient, override)
mozilla::dom::quota::Client::Type
GetType() override;
@ -20420,14 +20421,14 @@ MutableFile::CreateStream(bool aReadOnly)
if (aReadOnly) {
RefPtr<FileInputStream> stream =
FileInputStream::Create(persistenceType, group, origin, mFile, -1, -1,
nsIFileInputStream::DEFER_OPEN);
CreateFileInputStream(persistenceType, group, origin, mFile, -1, -1,
nsIFileInputStream::DEFER_OPEN);
result = NS_ISUPPORTS_CAST(nsIFileInputStream*, stream);
}
else {
RefPtr<FileStream> stream =
FileStream::Create(persistenceType, group, origin, mFile, -1, -1,
nsIFileStream::DEFER_OPEN);
CreateFileStream(persistenceType, group, origin, mFile, -1, -1,
nsIFileStream::DEFER_OPEN);
result = NS_ISUPPORTS_CAST(nsIFileStream*, stream);
}
if (NS_WARN_IF(!result)) {
@ -29087,10 +29088,10 @@ FileHelper::CreateFileFromStream(nsIFile* aFile,
// Now try to copy the stream.
RefPtr<FileOutputStream> fileOutputStream =
FileOutputStream::Create(mFileManager->Type(),
mFileManager->Group(),
mFileManager->Origin(),
aFile);
CreateFileOutputStream(mFileManager->Type(),
mFileManager->Group(),
mFileManager->Origin(),
aFile);
if (NS_WARN_IF(!fileOutputStream)) {
return NS_ERROR_FAILURE;
}

View file

@ -101,6 +101,7 @@ DIRS += [
'payments',
'websocket',
'serviceworkers',
'simpledb',
]
if CONFIG['OS_ARCH'] == 'WINNT':

View file

@ -365,58 +365,52 @@ PaymentDetails::Create(const IPCPaymentDetails& aIPCDetails,
}
nsCOMPtr<nsIArray> displayItems;
if (aIPCDetails.displayItemsPassed()) {
nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
MOZ_ASSERT(items);
for (const IPCPaymentItem& displayItem : aIPCDetails.displayItems()) {
nsCOMPtr<nsIPaymentItem> item;
rv = PaymentItem::Create(displayItem, getter_AddRefs(item));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = items->AppendElement(item);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
MOZ_ASSERT(items);
for (const IPCPaymentItem& displayItem : aIPCDetails.displayItems()) {
nsCOMPtr<nsIPaymentItem> item;
rv = PaymentItem::Create(displayItem, getter_AddRefs(item));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = items->AppendElement(item);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
displayItems = items.forget();
}
displayItems = items.forget();
nsCOMPtr<nsIArray> shippingOptions;
if (aIPCDetails.shippingOptionsPassed()) {
nsCOMPtr<nsIMutableArray> options = do_CreateInstance(NS_ARRAY_CONTRACTID);
MOZ_ASSERT(options);
for (const IPCPaymentShippingOption& shippingOption : aIPCDetails.shippingOptions()) {
nsCOMPtr<nsIPaymentShippingOption> option;
rv = PaymentShippingOption::Create(shippingOption, getter_AddRefs(option));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = options->AppendElement(option);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIMutableArray> options = do_CreateInstance(NS_ARRAY_CONTRACTID);
MOZ_ASSERT(options);
for (const IPCPaymentShippingOption& shippingOption : aIPCDetails.shippingOptions()) {
nsCOMPtr<nsIPaymentShippingOption> option;
rv = PaymentShippingOption::Create(shippingOption, getter_AddRefs(option));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = options->AppendElement(option);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
shippingOptions = options.forget();
}
shippingOptions = options.forget();
nsCOMPtr<nsIArray> modifiers;
if (aIPCDetails.modifiersPassed()) {
nsCOMPtr<nsIMutableArray> detailsModifiers = do_CreateInstance(NS_ARRAY_CONTRACTID);
MOZ_ASSERT(detailsModifiers);
for (const IPCPaymentDetailsModifier& modifier : aIPCDetails.modifiers()) {
nsCOMPtr<nsIPaymentDetailsModifier> detailsModifier;
rv = PaymentDetailsModifier::Create(modifier, getter_AddRefs(detailsModifier));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = detailsModifiers->AppendElement(detailsModifier);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIMutableArray> detailsModifiers = do_CreateInstance(NS_ARRAY_CONTRACTID);
MOZ_ASSERT(detailsModifiers);
for (const IPCPaymentDetailsModifier& modifier : aIPCDetails.modifiers()) {
nsCOMPtr<nsIPaymentDetailsModifier> detailsModifier;
rv = PaymentDetailsModifier::Create(modifier, getter_AddRefs(detailsModifier));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = detailsModifiers->AppendElement(detailsModifier);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
modifiers = detailsModifiers.forget();
}
modifiers = detailsModifiers.forget();
nsCOMPtr<nsIPaymentDetails> details =
new PaymentDetails(aIPCDetails.id(), total, displayItems, shippingOptions,

View file

@ -178,10 +178,7 @@ ConvertDetailsInit(JSContext* aCx,
shippingOptions,
modifiers,
EmptyString(), // error message
EmptyString(), // shippingAddressErrors
aDetails.mDisplayItems.WasPassed(),
aDetails.mShippingOptions.WasPassed(),
aDetails.mModifiers.WasPassed());
EmptyString()); // shippingAddressErrors
return NS_OK;
}
@ -223,10 +220,7 @@ ConvertDetailsUpdate(JSContext* aCx,
shippingOptions,
modifiers,
error,
shippingAddressErrors,
aDetails.mDisplayItems.WasPassed(),
aDetails.mShippingOptions.WasPassed(),
aDetails.mModifiers.WasPassed());
shippingAddressErrors);
return NS_OK;
}

View file

@ -56,9 +56,6 @@ struct IPCPaymentDetails
IPCPaymentDetailsModifier[] modifiers;
nsString error;
nsString shippingAddressErrors;
bool displayItemsPassed;
bool shippingOptionsPassed;
bool modifiersPassed;
};
struct IPCPaymentOptions

View file

@ -45,14 +45,14 @@ function checkSimplestRequest(payRequest) {
emitTestFail("total item's value should be '1.00'.");
}
if (details.displayItems) {
emitTestFail("details.displayItems should be undefined.");
if (details.displayItems.length !== 0) {
emitTestFail("details.displayItems should be an empty array.");
}
if (details.modifiers) {
emitTestFail("details.displayItems should be undefined.");
if (details.modifiers.length !== 0) {
emitTestFail("details.modifiers should be an empty array.");
}
if (details.shippingOptions) {
emitTestFail("details.shippingOptions should be undefined.");
if (details.shippingOptions.length !== 0) {
emitTestFail("details.shippingOptions should be an empty array.");
}
// checking the default generated PaymentOptions parameter
@ -319,14 +319,14 @@ function checkNonBasicCardRequest(payRequest) {
emitTestFail("total item's value should be '1.00'.");
}
if (details.displayItems) {
emitTestFail("details.displayItems should be undefined.");
if (details.displayItems.length !== 0) {
emitTestFail("details.displayItems should be an zero length array.");
}
if (details.modifiers) {
emitTestFail("details.displayItems should be undefined.");
if (details.displayItems.length !== 0) {
emitTestFail("details.modifiers should be an zero length array.");
}
if (details.shippingOptions) {
emitTestFail("details.shippingOptions should be undefined.");
if (details.displayItems.length !== 0) {
emitTestFail("details.shippingOptions should be an zero length array.");
}
// checking the default generated PaymentOptions parameter

View file

@ -2,30 +2,38 @@
// kTestRoot is from head.js
const kTestPage = kTestRoot + "simple_payment_request.html";
add_task(async function() {
const TABS_TO_OPEN = 5;
add_task(async () => {
Services.prefs.setBoolPref("dom.payments.request.enabled", true);
await BrowserTestUtils.withNewTab(kTestPage,
async function(browser) {
await BrowserTestUtils.withNewTab(kTestPage,
function(browser) {
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
ok(paymentSrv, "Fail to get PaymentRequestService.");
const paymentEnum = paymentSrv.enumerate();
ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
let tabIds = [];
while (paymentEnum.hasMoreElements()) {
let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
ok(payment, "Fail to get existing payment request.");
checkSimplePayment(payment);
tabIds.push(payment.tabId);
}
is(tabIds.length, 2, "TabId array length should be 2.");
ok(tabIds[0] != tabIds[1], "TabIds should be different.");
Services.prefs.setBoolPref("dom.payments.request.enabled", false);
}
);
}
const tabs = [];
const options = {
gBrowser: Services.wm.getMostRecentWindow("navigator:browser").gBrowser,
url: kTestPage,
};
for (let i = 0; i < TABS_TO_OPEN; i++) {
const tab = await BrowserTestUtils.openNewForegroundTab(options);
tabs.push(tab);
}
const paymentSrv = Cc[
"@mozilla.org/dom/payments/payment-request-service;1"
].getService(Ci.nsIPaymentRequestService);
ok(paymentSrv, "Fail to get PaymentRequestService.");
const paymentEnum = paymentSrv.enumerate();
ok(
paymentEnum.hasMoreElements(),
"PaymentRequestService should have at least one payment request."
);
const payments = new Set();
while (paymentEnum.hasMoreElements()) {
const payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
ok(payment, "Fail to get existing payment request.");
checkSimplePayment(payment);
payments.add(payment);
}
is(payments.size, TABS_TO_OPEN, `Should be ${TABS_TO_OPEN} unique objects.`);
tabs.forEach(async tab => {
await TestUtils.waitForTick();
BrowserTestUtils.removeTab(tab);
});
Services.prefs.setBoolPref("dom.payments.request.enabled", false);
});

View file

@ -17,9 +17,9 @@ function checkSimplePayment(aSimplePayment) {
is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
ok(!details.displayItems, "details.displayItems should be undefined.");
ok(!details.modifiers, "details.modifiers should be undefined.");
ok(!details.shippingOptions, "details.shippingOptions should be undefined.");
is(details.displayItems.length, 0, "details.displayItems should be a zero length array.");
is(details.modifiers.length, 0, "details.modifiers should be a zero length array.");
is(details.shippingOptions.length, 0, "details.shippingOptions should be a zero length array.");
// checking the default generated PaymentOptions parameter
const paymentOptions = aSimplePayment.paymentOptions;

View file

@ -1,47 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>Payment Request Testing</title>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
</head>
<body>
<h1>simple payment request.html</h1>
<script type="text/javascript">
<!doctype html>
<meta charset="utf-8">
<title>Payment Request Testing</title>
<script>
const methods = [
{
supportedMethods: "basic-card",
},
];
const details = {
id: "simple details",
total: {
label: "Donation",
amount: { currency: "USD", value: "55.00" },
},
};
const supportedInstruments = [{
supportedMethods: "basic-card",
}];
const details = {
id: "simple details",
total: {
label: "Donation",
amount: { currency: "USD", value: "55.00" }
},
};
let request;
let msg = "successful";
try {
request = new PaymentRequest(methods, details);
} catch (err) {
msg = err.name;
}
window.parent.postMessage(msg, "*");
try {
const payRequest = new PaymentRequest(supportedInstruments, details);
window.onmessage = async (e) => {
if (e.data === "show PaymentRequest") {
if (payRequest) {
payRequest.show();
window.parent.postMessage("successful", '*');
} else {
window.parent.postMessage("PaymentRequest does not exist", "*");
}
}
}
if(window.parent) {
window.parent.postMessage("successful", '*');
}
} catch(err) {
if(window.parent) {
window.parent.postMessage(err.name, '*');
}
if (request) {
window.onmessage = async ({ data: action }) => {
switch (action) {
case "show PaymentRequest":
const responsePromise = request.show();
window.parent.postMessage("successful", "*");
try {
await responsePromise;
} catch (err) { /* graceful abort */ }
break;
default:
window.parent.postMessage(`fail - unknown postmessage action: ${action}`, "*");
}
</script>
</body>
</html>
};
}
</script>

View file

@ -36,6 +36,7 @@
#include "mozilla/dom/quota/PQuotaParent.h"
#include "mozilla/dom/quota/PQuotaRequestParent.h"
#include "mozilla/dom/quota/PQuotaUsageRequestParent.h"
#include "mozilla/dom/simpledb/ActorsParent.h"
#include "mozilla/dom/StorageActivityService.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
@ -3600,8 +3601,12 @@ QuotaManager::Init(const nsAString& aBasePath)
return NS_ERROR_FAILURE;
}
static_assert(Client::IDB == 0 && Client::ASMJS == 1 && Client::DOMCACHE == 2 &&
Client::TYPE_MAX == 3, "Fix the registration!");
static_assert(Client::IDB == 0 &&
Client::ASMJS == 1 &&
Client::DOMCACHE == 2 &&
Client::SDB == 3 &&
Client::TYPE_MAX == 4,
"Fix the registration!");
MOZ_ASSERT(mClients.Capacity() == Client::TYPE_MAX,
"Should be using an auto array with correct capacity!");
@ -3610,6 +3615,7 @@ QuotaManager::Init(const nsAString& aBasePath)
mClients.AppendElement(indexedDB::CreateQuotaClient());
mClients.AppendElement(asmjscache::CreateClient());
mClients.AppendElement(cache::CreateQuotaClient());
mClients.AppendElement(simpledb::CreateQuotaClient());
return NS_OK;
}

View file

@ -19,6 +19,7 @@ class nsIRunnable;
#define IDB_DIRECTORY_NAME "idb"
#define ASMJSCACHE_DIRECTORY_NAME "asmjs"
#define DOMCACHE_DIRECTORY_NAME "cache"
#define SDB_DIRECTORY_NAME "sdb"
#define LS_DIRECTORY_NAME "ls"
BEGIN_QUOTA_NAMESPACE
@ -42,6 +43,7 @@ public:
//APPCACHE,
ASMJS,
DOMCACHE,
SDB,
TYPE_MAX
};
@ -64,6 +66,10 @@ public:
aText.AssignLiteral(DOMCACHE_DIRECTORY_NAME);
break;
case SDB:
aText.AssignLiteral(SDB_DIRECTORY_NAME);
break;
case TYPE_MAX:
default:
MOZ_ASSERT_UNREACHABLE("Bad id value!");
@ -85,6 +91,9 @@ public:
else if (aText.EqualsLiteral(DOMCACHE_DIRECTORY_NAME)) {
aType = DOMCACHE;
}
else if (aText.EqualsLiteral(SDB_DIRECTORY_NAME)) {
aType = SDB;
}
else {
return NS_ERROR_FAILURE;
}

View file

@ -9,7 +9,7 @@
#include "QuotaManager.h"
#include "prio.h"
USING_QUOTA_NAMESPACE
BEGIN_QUOTA_NAMESPACE
template <class FileStreamBase>
NS_IMETHODIMP
@ -91,10 +91,13 @@ FileQuotaStreamWithWrite<FileStreamBase>::Write(const char* aBuf,
}
already_AddRefed<FileInputStream>
FileInputStream::Create(PersistenceType aPersistenceType,
const nsACString& aGroup, const nsACString& aOrigin,
nsIFile* aFile, int32_t aIOFlags, int32_t aPerm,
int32_t aBehaviorFlags)
CreateFileInputStream(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
nsIFile* aFile,
int32_t aIOFlags,
int32_t aPerm,
int32_t aBehaviorFlags)
{
RefPtr<FileInputStream> stream =
new FileInputStream(aPersistenceType, aGroup, aOrigin);
@ -104,10 +107,13 @@ FileInputStream::Create(PersistenceType aPersistenceType,
}
already_AddRefed<FileOutputStream>
FileOutputStream::Create(PersistenceType aPersistenceType,
const nsACString& aGroup, const nsACString& aOrigin,
nsIFile* aFile, int32_t aIOFlags, int32_t aPerm,
int32_t aBehaviorFlags)
CreateFileOutputStream(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
nsIFile* aFile,
int32_t aIOFlags,
int32_t aPerm,
int32_t aBehaviorFlags)
{
RefPtr<FileOutputStream> stream =
new FileOutputStream(aPersistenceType, aGroup, aOrigin);
@ -117,9 +123,13 @@ FileOutputStream::Create(PersistenceType aPersistenceType,
}
already_AddRefed<FileStream>
FileStream::Create(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags,
int32_t aPerm, int32_t aBehaviorFlags)
CreateFileStream(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
nsIFile* aFile,
int32_t aIOFlags,
int32_t aPerm,
int32_t aBehaviorFlags)
{
RefPtr<FileStream> stream =
new FileStream(aPersistenceType, aGroup, aOrigin);
@ -127,3 +137,5 @@ FileStream::Create(PersistenceType aPersistenceType, const nsACString& aGroup,
NS_ENSURE_SUCCESS(rv, nullptr);
return stream.forget();
}
END_QUOTA_NAMESPACE

View file

@ -64,17 +64,12 @@ public:
NS_INLINE_DECL_REFCOUNTING_INHERITED(FileInputStream,
FileQuotaStream<nsFileInputStream>)
static already_AddRefed<FileInputStream>
Create(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
private:
FileInputStream(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin)
: FileQuotaStream<nsFileInputStream>(aPersistenceType, aGroup, aOrigin)
{ }
private:
virtual ~FileInputStream() {
Close();
}
@ -86,18 +81,13 @@ public:
NS_INLINE_DECL_REFCOUNTING_INHERITED(FileOutputStream,
FileQuotaStreamWithWrite<nsFileOutputStream>);
static already_AddRefed<FileOutputStream>
Create(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
private:
FileOutputStream(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin)
: FileQuotaStreamWithWrite<nsFileOutputStream>(aPersistenceType, aGroup,
aOrigin)
{ }
private:
virtual ~FileOutputStream() {
Close();
}
@ -109,22 +99,44 @@ public:
NS_INLINE_DECL_REFCOUNTING_INHERITED(FileStream,
FileQuotaStreamWithWrite<nsFileStream>)
static already_AddRefed<FileStream>
Create(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
private:
FileStream(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin)
: FileQuotaStreamWithWrite<nsFileStream>(aPersistenceType, aGroup, aOrigin)
{ }
private:
virtual ~FileStream() {
Close();
}
};
already_AddRefed<FileInputStream>
CreateFileInputStream(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
nsIFile* aFile,
int32_t aIOFlags = -1,
int32_t aPerm = -1,
int32_t aBehaviorFlags = 0);
already_AddRefed<FileOutputStream>
CreateFileOutputStream(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
nsIFile* aFile,
int32_t aIOFlags = -1,
int32_t aPerm = -1,
int32_t aBehaviorFlags = 0);
already_AddRefed<FileStream>
CreateFileStream(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
nsIFile* aFile,
int32_t aIOFlags = -1,
int32_t aPerm = -1,
int32_t aBehaviorFlags = 0);
END_QUOTA_NAMESPACE
#endif /* mozilla_dom_quota_filestreams_h__ */

View file

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MemoryOutputStream.h"
#include "nsStreamUtils.h"
namespace mozilla {
namespace dom {
namespace quota {
// static
already_AddRefed<MemoryOutputStream>
MemoryOutputStream::Create(uint64_t aSize)
{
MOZ_ASSERT(aSize, "Passed zero size!");
if (NS_WARN_IF(aSize > UINT32_MAX)) {
return nullptr;
}
RefPtr<MemoryOutputStream> stream = new MemoryOutputStream();
char* dummy;
uint32_t length = stream->mData.GetMutableData(&dummy, aSize, fallible);
if (NS_WARN_IF(length != aSize)) {
return nullptr;
}
return stream.forget();
}
NS_IMPL_ISUPPORTS(MemoryOutputStream, nsIOutputStream)
NS_IMETHODIMP
MemoryOutputStream::Close()
{
mData.Truncate(mOffset);
return NS_OK;
}
NS_IMETHODIMP
MemoryOutputStream::Write(const char* aBuf, uint32_t aCount, uint32_t* _retval)
{
return WriteSegments(NS_CopySegmentToBuffer, (char*)aBuf, aCount, _retval);
}
NS_IMETHODIMP
MemoryOutputStream::Flush()
{
return NS_OK;
}
NS_IMETHODIMP
MemoryOutputStream::WriteFrom(nsIInputStream* aFromStream, uint32_t aCount,
uint32_t* _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MemoryOutputStream::WriteSegments(nsReadSegmentFun aReader, void* aClosure,
uint32_t aCount, uint32_t* _retval)
{
MOZ_ASSERT(mData.Length() >= mOffset, "Bad stream state!");
uint32_t maxCount = mData.Length() - mOffset;
if (maxCount == 0) {
*_retval = 0;
return NS_OK;
}
if (aCount > maxCount) {
aCount = maxCount;
}
nsresult rv = aReader(this, aClosure, mData.BeginWriting() + mOffset, 0,
aCount, _retval);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(*_retval <= aCount,
"Reader should not read more than we asked it to read!");
mOffset += *_retval;
}
return NS_OK;
}
NS_IMETHODIMP
MemoryOutputStream::IsNonBlocking(bool* _retval)
{
*_retval = false;
return NS_OK;
}
} // namespace quota
} // namespace dom
} // namespace mozilla

View file

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_quota_MemoryOutputStream_h
#define mozilla_dom_quota_MemoryOutputStream_h
#include "nsIOutputStream.h"
namespace mozilla {
namespace dom {
namespace quota {
// An output stream so you can read your potentially-async input stream into
// a contiguous buffer in the form of an nsCString using NS_AsyncCopy.
// Back when streams were more synchronous and people didn't know blocking I/O
// was bad, if you wanted to read a stream into a flat buffer, you could use
// NS_ReadInputStreamToString/NS_ReadInputStreamToBuffer. But those don't work
// with async streams. This can be used to replace hand-rolled Read/AsyncWait()
// loops. Because you specify the expected size up front, the nsCString buffer
// is pre-allocated so wasteful reallocations can be avoided. However,
// nsCString currently may over-allocate and this can be problematic on 32-bit
// windows until we're rid of that build configuration.
class MemoryOutputStream final
: public nsIOutputStream
{
nsCString mData;
uint64_t mOffset;
public:
static already_AddRefed<MemoryOutputStream>
Create(uint64_t aSize);
const nsCString&
Data() const
{
return mData;
}
private:
MemoryOutputStream()
: mOffset(0)
{ }
virtual ~MemoryOutputStream()
{ }
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOUTPUTSTREAM
};
} // namespace quota
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_quota_MemoryOutputStream_h */

View file

@ -19,6 +19,8 @@
#include "nsIQuotaRequests.h"
#include "nsPIDOMWindow.h"
using namespace mozilla::dom::quota;
namespace mozilla {
namespace dom {

View file

@ -15,6 +15,10 @@ XPCSHELL_TESTS_MANIFESTS += [
'test/unit/xpcshell.ini'
]
TEST_HARNESS_FILES.xpcshell.dom.quota.test += [
'test/head-shared.js',
]
XPIDL_SOURCES += [
'nsIQuotaCallbacks.idl',
'nsIQuotaManagerService.idl',
@ -32,6 +36,7 @@ EXPORTS.mozilla.dom.quota += [
'ActorsParent.h',
'Client.h',
'FileStreams.h',
'MemoryOutputStream.h',
'OriginScope.h',
'PersistenceType.h',
'QuotaCommon.h',
@ -46,6 +51,7 @@ UNIFIED_SOURCES += [
'ActorsChild.cpp',
'ActorsParent.cpp',
'FileStreams.cpp',
'MemoryOutputStream.cpp',
'QuotaManagerService.cpp',
'QuotaRequests.cpp',
'QuotaResults.cpp',

View file

@ -1,10 +1,12 @@
[DEFAULT]
skip-if = (buildapp != "browser")
support-files =
head.js
browserHelpers.js
browser_permissionsPrompt.html
head-shared.js
head.js
[browser_permissionsPromptAllow.js]
[browser_permissionsPromptDeny.js]
[browser_permissionsPromptUnknown.js]
[browser_simpledb.js]

View file

@ -0,0 +1,50 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
add_task(async function testSimpleDB() {
const name = "data";
const bufferSize = 100;
await SpecialPowers.pushPrefEnv({ set: [[ "dom.simpleDB.enabled", true ]] });
let database = getSimpleDatabase();
let request = database.open("data");
await requestFinished(request);
let buffer1 = getRandomBuffer(bufferSize);
request = database.write(buffer1);
await requestFinished(request);
request = database.seek(0);
await requestFinished(request);
request = database.read(bufferSize);
let result = await requestFinished(request);
let buffer2 = result.getAsArrayBuffer();
ok(compareBuffers(buffer1, buffer2), "Buffers equal.");
let database2 = getSimpleDatabase();
try {
request = database2.open(name);
await requestFinished(request);
ok(false, "Should have thrown!");
} catch(ex) {
ok(request.resultCode == NS_ERROR_STORAGE_BUSY, "Good result code.");
}
request = database.close();
await requestFinished(request);
request = database2.open(name);
await requestFinished(request);
request = database2.close();
await requestFinished(request);
});

View file

@ -0,0 +1,37 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
function getBuffer(size)
{
let buffer = new ArrayBuffer(size);
is(buffer.byteLength, size, "Correct byte length");
return buffer;
}
function getRandomBuffer(size)
{
let buffer = getBuffer(size);
let view = new Uint8Array(buffer);
for (let i = 0; i < size; i++) {
view[i] = parseInt(Math.random() * 255)
}
return buffer;
}
function compareBuffers(buffer1, buffer2)
{
if (buffer1.byteLength != buffer2.byteLength) {
return false;
}
let view1 = buffer1 instanceof Uint8Array ? buffer1 : new Uint8Array(buffer1);
let view2 = buffer2 instanceof Uint8Array ? buffer2 : new Uint8Array(buffer2);
for (let i = 0; i < buffer1.byteLength; i++) {
if (view1[i] != view2[i]) {
return false;
}
}
return true;
}

View file

@ -3,6 +3,8 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const NS_ERROR_STORAGE_BUSY = Cr.NS_ERROR_STORAGE_BUSY;
var gActiveListeners = {};
// These event (un)registration handlers only work for one window, DONOT use
@ -136,3 +138,37 @@ function getPermission(url, permission)
.getService(Ci.nsIPermissionManager)
.testPermissionFromPrincipal(principal, permission);
}
function getCurrentPrincipal()
{
return Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
}
function getSimpleDatabase(principal)
{
let connection = Cc["@mozilla.org/dom/sdb-connection;1"]
.createInstance(Ci.nsISDBConnection);
if (!principal) {
principal = getCurrentPrincipal();
}
connection.init(principal);
return connection;
}
function requestFinished(request) {
return new Promise(function(resolve, reject) {
request.callback = function(request) {
if (request.resultCode == Cr.NS_OK) {
resolve(request.result);
} else {
reject(request.resultCode);
}
}
});
}
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/dom/quota/test/head-shared.js", this);

View file

@ -3,6 +3,8 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const NS_ERROR_STORAGE_BUSY = SpecialPowers.Cr.NS_ERROR_STORAGE_BUSY;
var testGenerator = testSteps();
function clearAllDatabases(callback)
@ -47,6 +49,7 @@ function* testHarnessSteps()
"set": [
["dom.storageManager.enabled", true],
["dom.storageManager.prompt.testing", true],
["dom.simpleDB.enabled", true],
]
},
nextTestHarnessStep
@ -138,6 +141,12 @@ function* testHarnessSteps()
info("Running test in main thread");
let script = document.createElement("script");
script.src = "head-shared.js";
script.onload = nextTestHarnessStep;
document.head.appendChild(script);
yield undefined;
// Now run the test script in the main thread.
testGenerator.next();
@ -304,3 +313,54 @@ function workerScript()
self.postMessage({ op: "ready" });
}
// SimpleDB connections and SpecialPowers wrapping:
//
// SpecialPowers provides a SpecialPowersHandler Proxy mechanism that lets our
// content-privileged code borrow its chrome-privileged principal to access
// things we shouldn't be able to access. The proxies wrap their returned
// values, so once we have something wrapped we can rely on returned objects
// being wrapped as well. The proxy will also automatically unwrap wrapped
// arguments we pass in. However, we need to invoke wrapCallback on callback
// functions so that the arguments they receive will be wrapped because the
// proxy does not automatically wrap content-privileged functions.
//
// Our use of (wrapped) SpecialPowers.Cc results in getSimpleDatabase()
// producing a wrapped nsISDBConnection instance. The nsISDBResult instances
// exposed on the (wrapped) nsISDBRequest are also wrapped, so our
// requestFinished helper wraps the results in helper objects that behave the
// same as the result, automatically unwrapping the wrapped array/arraybuffer
// results.
function getSimpleDatabase()
{
let connection = SpecialPowers.Cc["@mozilla.org/dom/sdb-connection;1"]
.createInstance(SpecialPowers.Ci.nsISDBConnection);
let principal = SpecialPowers.wrap(document).nodePrincipal;
connection.init(principal);
return connection;
}
function* requestFinished(request) {
request.callback = SpecialPowers.wrapCallback(continueToNextStepSync);
yield undefined;
if (request.resultCode == SpecialPowers.Cr.NS_OK) {
let result = request.result;
if (SpecialPowers.call_Instanceof(result, SpecialPowers.Ci.nsISDBResult)) {
let wrapper = {};
for (let i in result) {
if (typeof result[i] == "function") {
wrapper[i] = SpecialPowers.unwrap(result[i]);
} else {
wrapper[i] = result[i];
}
}
return wrapper;
}
return result;
}
throw request.resultCode;
}

View file

@ -4,11 +4,14 @@
[DEFAULT]
support-files =
head-shared.js
helpers.js
unit/test_simpledb.js
unit/test_storage_manager_persist_allow.js
unit/test_storage_manager_persist_deny.js
unit/test_storage_manager_persisted.js
[test_simpledb.html]
[test_storage_manager_persist_allow.html]
scheme=https
[test_storage_manager_persist_deny.html]

View file

@ -0,0 +1,19 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>SimpleDB Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="unit/test_simpledb.js"></script>
<script type="text/javascript" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View file

@ -6,15 +6,16 @@
const NS_OK = Cr.NS_OK;
const NS_ERROR_FAILURE = Cr.NS_ERROR_FAILURE;
const NS_ERROR_UNEXPECTED = Cr.NS_ERROR_UNEXPECTED;
const NS_ERROR_STORAGE_BUSY = Cr.NS_ERROR_STORAGE_BUSY;
function is(a, b, msg)
{
Assert.equal(a, b, Components.stack.caller);
Assert.equal(a, b, msg);
}
function ok(cond, msg)
{
Assert.ok(!!cond, Components.stack.caller);
Assert.ok(!!cond, msg);
}
function run_test()
@ -65,11 +66,13 @@ function continueToNextStepSync()
function enableTesting()
{
SpecialPowers.setBoolPref("dom.quotaManager.testing", true);
SpecialPowers.setBoolPref("dom.simpleDB.enabled", true);
}
function resetTesting()
{
SpecialPowers.clearUserPref("dom.quotaManager.testing");
SpecialPowers.clearUserPref("dom.simpleDB.enabled");
}
function init(callback)
@ -229,22 +232,6 @@ function getRelativeFile(relativePath)
return file;
}
function compareBuffers(buffer1, buffer2)
{
if (buffer1.byteLength != buffer2.byteLength) {
return false;
}
let view1 = buffer1 instanceof Uint8Array ? buffer1 : new Uint8Array(buffer1);
let view2 = buffer2 instanceof Uint8Array ? buffer2 : new Uint8Array(buffer2);
for (let i = 0; i < buffer1.byteLength; i++) {
if (view1[i] != view2[i]) {
return false;
}
}
return true;
}
function getPersistedFromMetadata(readBuffer)
{
const persistedPosition = 8; // Persisted state is stored in the 9th byte
@ -292,6 +279,34 @@ function getPrincipal(url)
return ssm.createCodebasePrincipal(uri, {});
}
function getCurrentPrincipal()
{
return Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
}
function getSimpleDatabase(principal)
{
let connection = Cc["@mozilla.org/dom/sdb-connection;1"]
.createInstance(Ci.nsISDBConnection);
if (!principal) {
principal = getCurrentPrincipal();
}
connection.init(principal);
return connection;
}
function* requestFinished(request) {
request.callback = continueToNextStepSync;
yield undefined;
if (request.resultCode == NS_OK) {
return request.result;
}
throw request.resultCode;
}
var SpecialPowers = {
getBoolPref: function(prefName) {
return this._getPrefs().getBoolPref(prefName);
@ -316,3 +331,15 @@ var SpecialPowers = {
.getService(Ci.nsIQuotaManagerService);
},
};
function loadSubscript(path)
{
let file = do_get_file(path, false);
let uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService).newFileURI(file);
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
scriptLoader.loadSubScript(uri.spec);
}
loadSubscript("../head-shared.js");

View file

@ -0,0 +1,55 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var disableWorkerTest = "SimpleDB doesn't work in workers yet";
var testGenerator = testSteps();
function* testSteps()
{
const name = "data";
const bufferSize = 100;
let database = getSimpleDatabase();
let request = database.open(name);
yield* requestFinished(request);
let buffer1 = getRandomBuffer(bufferSize);
request = database.write(buffer1);
yield* requestFinished(request);
request = database.seek(0);
yield* requestFinished(request);
request = database.read(bufferSize);
let result = yield* requestFinished(request);
let buffer2 = result.getAsArrayBuffer();
ok(compareBuffers(buffer1, buffer2), "Buffers equal.");
let database2 = getSimpleDatabase();
try {
request = database2.open(name);
yield* requestFinished(request);
ok(false, "Should have thrown!");
} catch(ex) {
ok(request.resultCode == NS_ERROR_STORAGE_BUSY, "Good result code.");
}
request = database.close();
yield* requestFinished(request);
request = database2.open(name);
yield* requestFinished(request);
request = database2.close();
yield* requestFinished(request);
finishTest();
}

View file

@ -32,6 +32,7 @@ skip-if = release_or_beta
[test_persist.js]
[test_removeAppsUpgrade.js]
[test_removeLocalStorage.js]
[test_simpledb.js]
[test_storagePersistentUpgrade.js]
[test_tempMetadataCleanup.js]
[test_unknownFiles.js]

View file

@ -0,0 +1,243 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ActorsChild.h"
#include "nsVariant.h"
#include "SDBConnection.h"
#include "SDBRequest.h"
#include "SDBResults.h"
namespace mozilla {
namespace dom {
/*******************************************************************************
* SDBConnectionChild
******************************************************************************/
SDBConnectionChild::SDBConnectionChild(SDBConnection* aConnection)
: mConnection(aConnection)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aConnection);
MOZ_COUNT_CTOR(SDBConnectionChild);
}
SDBConnectionChild::~SDBConnectionChild()
{
AssertIsOnOwningThread();
MOZ_COUNT_DTOR(SDBConnectionChild);
}
void
SDBConnectionChild::SendDeleteMeInternal()
{
AssertIsOnOwningThread();
if (mConnection) {
mConnection->ClearBackgroundActor();
mConnection = nullptr;
MOZ_ALWAYS_TRUE(PBackgroundSDBConnectionChild::SendDeleteMe());
}
}
void
SDBConnectionChild::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnOwningThread();
if (mConnection) {
mConnection->ClearBackgroundActor();
#ifdef DEBUG
mConnection = nullptr;
#endif
}
}
PBackgroundSDBRequestChild*
SDBConnectionChild::AllocPBackgroundSDBRequestChild(
const SDBRequestParams& aParams)
{
AssertIsOnOwningThread();
MOZ_CRASH("PBackgroundSDBRequestChild actors should be manually "
"constructed!");
}
bool
SDBConnectionChild::DeallocPBackgroundSDBRequestChild(
PBackgroundSDBRequestChild* aActor)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aActor);
delete static_cast<SDBRequestChild*>(aActor);
return true;
}
mozilla::ipc::IPCResult
SDBConnectionChild::RecvAllowToClose()
{
AssertIsOnOwningThread();
if (mConnection) {
mConnection->AllowToClose();
}
return IPC_OK();
}
mozilla::ipc::IPCResult
SDBConnectionChild::RecvClosed()
{
AssertIsOnOwningThread();
if (mConnection) {
mConnection->OnClose(/* aAbnormal */ true);
}
return IPC_OK();
}
/*******************************************************************************
* SDBRequestChild
******************************************************************************/
SDBRequestChild::SDBRequestChild(SDBRequest* aRequest)
: mConnection(aRequest->GetConnection())
, mRequest(aRequest)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aRequest);
MOZ_COUNT_CTOR(SDBRequestChild);
}
SDBRequestChild::~SDBRequestChild()
{
AssertIsOnOwningThread();
MOZ_COUNT_DTOR(SDBRequestChild);
}
#ifdef DEBUG
void
SDBRequestChild::AssertIsOnOwningThread() const
{
MOZ_ASSERT(mRequest);
mRequest->AssertIsOnOwningThread();
}
#endif // DEBUG
void
SDBRequestChild::HandleResponse(nsresult aResponse)
{
AssertIsOnOwningThread();
MOZ_ASSERT(NS_FAILED(aResponse));
MOZ_ASSERT(mRequest);
mRequest->SetError(aResponse);
}
void
SDBRequestChild::HandleResponse()
{
AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
RefPtr<nsVariant> variant = new nsVariant();
variant->SetAsVoid();
mRequest->SetResult(variant);
}
void
SDBRequestChild::HandleResponse(const nsCString& aResponse)
{
AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
RefPtr<SDBResult> result = new SDBResult(aResponse);
RefPtr<nsVariant> variant = new nsVariant();
variant->SetAsInterface(NS_GET_IID(nsISDBResult), result);
mRequest->SetResult(variant);
}
void
SDBRequestChild::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnOwningThread();
if (mConnection) {
mConnection->AssertIsOnOwningThread();
mConnection->OnRequestFinished();
#ifdef DEBUG
mConnection = nullptr;
#endif
}
}
mozilla::ipc::IPCResult
SDBRequestChild::Recv__delete__(const SDBRequestResponse& aResponse)
{
AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT(mConnection);
switch (aResponse.type()) {
case SDBRequestResponse::Tnsresult:
HandleResponse(aResponse.get_nsresult());
break;
case SDBRequestResponse::TSDBRequestOpenResponse:
HandleResponse();
mConnection->OnOpen();
break;
case SDBRequestResponse::TSDBRequestSeekResponse:
HandleResponse();
break;
case SDBRequestResponse::TSDBRequestReadResponse:
HandleResponse(aResponse.get_SDBRequestReadResponse().data());
break;
case SDBRequestResponse::TSDBRequestWriteResponse:
HandleResponse();
break;
case SDBRequestResponse::TSDBRequestCloseResponse:
HandleResponse();
mConnection->OnClose(/* aAbnormal */ false);
break;
default:
MOZ_CRASH("Unknown response type!");
}
mConnection->OnRequestFinished();
// Null this out so that we don't try to call OnRequestFinished() again in
// ActorDestroy.
mConnection = nullptr;
return IPC_OK();
}
} // namespace dom
} // namespace mozilla

115
dom/simpledb/ActorsChild.h Normal file
View file

@ -0,0 +1,115 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_simpledb_ActorsChild_h
#define mozilla_dom_simpledb_ActorsChild_h
#include "mozilla/dom/PBackgroundSDBConnectionChild.h"
#include "mozilla/dom/PBackgroundSDBRequestChild.h"
namespace mozilla {
namespace ipc {
class BackgroundChildImpl;
} // namespace ipc
namespace dom {
class SDBConnection;
class SDBRequest;
class SDBConnectionChild final
: public PBackgroundSDBConnectionChild
{
friend class mozilla::ipc::BackgroundChildImpl;
friend class SDBConnection;
SDBConnection* mConnection;
NS_DECL_OWNINGTHREAD
public:
void
AssertIsOnOwningThread() const
{
NS_ASSERT_OWNINGTHREAD(SDBConnectionChild);
}
private:
// Only created by SDBConnection.
explicit SDBConnectionChild(SDBConnection* aConnection);
// Only destroyed by mozilla::ipc::BackgroundChildImpl.
~SDBConnectionChild();
void
SendDeleteMeInternal();
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
virtual PBackgroundSDBRequestChild*
AllocPBackgroundSDBRequestChild(const SDBRequestParams& aParams) override;
virtual bool
DeallocPBackgroundSDBRequestChild(PBackgroundSDBRequestChild* aActor)
override;
virtual mozilla::ipc::IPCResult
RecvAllowToClose() override;
virtual mozilla::ipc::IPCResult
RecvClosed() override;
};
class SDBRequestChild final
: public PBackgroundSDBRequestChild
{
friend class SDBConnectionChild;
friend class SDBConnection;
RefPtr<SDBConnection> mConnection;
RefPtr<SDBRequest> mRequest;
public:
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
private:
// Only created by SDBConnection.
explicit SDBRequestChild(SDBRequest* aRequest);
// Only destroyed by SDBConnectionChild.
~SDBRequestChild();
void
HandleResponse(nsresult aResponse);
void
HandleResponse();
void
HandleResponse(const nsCString& aResponse);
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
virtual mozilla::ipc::IPCResult
Recv__delete__(const SDBRequestResponse& aResponse) override;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_simpledb_ActorsChild_h

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_simpledb_ActorsParent_h
#define mozilla_dom_simpledb_ActorsParent_h
template <class> struct already_AddRefed;
namespace mozilla {
namespace ipc {
class PrincipalInfo;
} // namespace ipc
namespace dom {
class PBackgroundSDBConnectionParent;
namespace quota {
class Client;
} // namespace quota
PBackgroundSDBConnectionParent*
AllocPBackgroundSDBConnectionParent(
const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
bool
RecvPBackgroundSDBConnectionConstructor(
PBackgroundSDBConnectionParent* aActor,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
bool
DeallocPBackgroundSDBConnectionParent(PBackgroundSDBConnectionParent* aActor);
namespace simpledb {
already_AddRefed<mozilla::dom::quota::Client>
CreateQuotaClient();
} // namespace simpledb
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_simpledb_ActorsParent_h

View file

@ -0,0 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PBackgroundSDBRequest;
namespace mozilla {
namespace dom {
struct SDBRequestOpenParams
{
nsString name;
};
struct SDBRequestSeekParams
{
uint64_t offset;
};
struct SDBRequestReadParams
{
uint64_t size;
};
struct SDBRequestWriteParams
{
nsCString data;
};
struct SDBRequestCloseParams
{
};
union SDBRequestParams
{
SDBRequestOpenParams;
SDBRequestSeekParams;
SDBRequestReadParams;
SDBRequestWriteParams;
SDBRequestCloseParams;
};
protocol PBackgroundSDBConnection
{
manager PBackground;
manages PBackgroundSDBRequest;
parent:
async DeleteMe();
async PBackgroundSDBRequest(SDBRequestParams params);
child:
async __delete__();
async AllowToClose();
async Closed();
};
} // namespace dom
} // namespace mozilla

View file

@ -0,0 +1,50 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundSDBConnection;
namespace mozilla {
namespace dom {
struct SDBRequestOpenResponse
{
};
struct SDBRequestSeekResponse
{
};
struct SDBRequestReadResponse
{
nsCString data;
};
struct SDBRequestWriteResponse
{
};
struct SDBRequestCloseResponse
{
};
union SDBRequestResponse
{
nsresult;
SDBRequestOpenResponse;
SDBRequestSeekResponse;
SDBRequestReadResponse;
SDBRequestWriteResponse;
SDBRequestCloseResponse;
};
protocol PBackgroundSDBRequest
{
manager PBackgroundSDBConnection;
child:
async __delete__(SDBRequestResponse response);
};
} // namespace dom
} // namespace mozilla

View file

@ -0,0 +1,428 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SDBConnection.h"
#include "ActorsChild.h"
#include "jsfriendapi.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "nsISDBCallbacks.h"
#include "SDBRequest.h"
#include "SimpleDBCommon.h"
namespace mozilla {
namespace dom {
using namespace mozilla::ipc;
namespace {
nsresult
GetWriteData(JSContext* aCx,
JS::Handle<JS::Value> aValue,
nsCString& aData)
{
if (aValue.isObject()) {
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
bool isView = false;
if (JS_IsArrayBufferObject(obj) ||
(isView = JS_IsArrayBufferViewObject(obj))) {
uint8_t* data;
uint32_t length;
bool unused;
if (isView) {
JS_GetObjectAsArrayBufferView(obj, &length, &unused, &data);
} else {
JS_GetObjectAsArrayBuffer(obj, &length, &data);
}
if (NS_WARN_IF(!aData.Assign(reinterpret_cast<char*>(data),
length,
fallible_t()))) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
}
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace
SDBConnection::SDBConnection()
: mBackgroundActor(nullptr)
, mRunningRequest(false)
, mOpen(false)
, mAllowedToClose(false)
{
AssertIsOnOwningThread();
}
SDBConnection::~SDBConnection()
{
AssertIsOnOwningThread();
if (mBackgroundActor) {
mBackgroundActor->SendDeleteMeInternal();
MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
}
}
// static
nsresult
SDBConnection::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
{
MOZ_ASSERT(aResult);
if (NS_WARN_IF(!Preferences::GetBool(kPrefSimpleDBEnabled, false))) {
return NS_ERROR_NOT_AVAILABLE;
}
if (aOuter) {
return NS_ERROR_NO_AGGREGATION;
}
RefPtr<SDBConnection> connection = new SDBConnection();
nsresult rv = connection->QueryInterface(aIID, aResult);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
void
SDBConnection::ClearBackgroundActor()
{
AssertIsOnOwningThread();
mBackgroundActor = nullptr;
}
void
SDBConnection::OnNewRequest()
{
AssertIsOnOwningThread();
MOZ_ASSERT(!mRunningRequest);
mRunningRequest = true;
}
void
SDBConnection::OnRequestFinished()
{
AssertIsOnOwningThread();
MOZ_ASSERT(mRunningRequest);
mRunningRequest = false;
}
void
SDBConnection::OnOpen()
{
AssertIsOnOwningThread();
MOZ_ASSERT(!mOpen);
mOpen = true;
}
void
SDBConnection::OnClose(bool aAbnormal)
{
AssertIsOnOwningThread();
MOZ_ASSERT(mOpen);
mOpen = false;
if (aAbnormal) {
MOZ_ASSERT(mAllowedToClose);
if (mCloseCallback) {
mCloseCallback->OnClose(this);
}
}
}
void
SDBConnection::AllowToClose()
{
AssertIsOnOwningThread();
mAllowedToClose = true;
}
nsresult
SDBConnection::CheckState()
{
AssertIsOnOwningThread();
if (mAllowedToClose) {
return NS_ERROR_ABORT;
}
if (mRunningRequest) {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
nsresult
SDBConnection::EnsureBackgroundActor()
{
AssertIsOnOwningThread();
if (mBackgroundActor) {
return NS_OK;
}
PBackgroundChild* backgroundActor =
BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!backgroundActor)) {
return NS_ERROR_FAILURE;
}
SDBConnectionChild* actor = new SDBConnectionChild(this);
mBackgroundActor =
static_cast<SDBConnectionChild*>(
backgroundActor->SendPBackgroundSDBConnectionConstructor(
actor,
*mPrincipalInfo));
if (NS_WARN_IF(!mBackgroundActor)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
SDBConnection::InitiateRequest(SDBRequest* aRequest,
const SDBRequestParams& aParams)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aRequest);
MOZ_ASSERT(mBackgroundActor);
auto actor = new SDBRequestChild(aRequest);
if (!mBackgroundActor->SendPBackgroundSDBRequestConstructor(actor, aParams)) {
return NS_ERROR_FAILURE;
}
// Balanced in SDBRequestChild::Recv__delete__().
OnNewRequest();
return NS_OK;
}
NS_IMPL_ISUPPORTS(SDBConnection, nsISDBConnection)
NS_IMETHODIMP
SDBConnection::Init(nsIPrincipal *aPrincipal)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo());
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, principalInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (principalInfo->type() != PrincipalInfo::TContentPrincipalInfo &&
principalInfo->type() != PrincipalInfo::TSystemPrincipalInfo) {
NS_WARNING("Simpledb not allowed for this principal!");
return NS_ERROR_INVALID_ARG;
}
mPrincipalInfo = std::move(principalInfo);
return NS_OK;
}
NS_IMETHODIMP
SDBConnection::Open(const nsAString& aName, nsISDBRequest** _retval)
{
AssertIsOnOwningThread();
nsresult rv = CheckState();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mOpen) {
return NS_ERROR_ALREADY_INITIALIZED;
}
SDBRequestOpenParams params;
params.name() = aName;
RefPtr<SDBRequest> request = new SDBRequest(this);
rv = EnsureBackgroundActor();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = InitiateRequest(request, params);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
SDBConnection::Seek(uint64_t aOffset, nsISDBRequest** _retval)
{
AssertIsOnOwningThread();
nsresult rv = CheckState();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!mOpen) {
return NS_BASE_STREAM_CLOSED;
}
SDBRequestSeekParams params;
params.offset() = aOffset;
RefPtr<SDBRequest> request = new SDBRequest(this);
rv = InitiateRequest(request, params);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
SDBConnection::Read(uint64_t aSize, nsISDBRequest** _retval)
{
AssertIsOnOwningThread();
nsresult rv = CheckState();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!mOpen) {
return NS_BASE_STREAM_CLOSED;
}
SDBRequestReadParams params;
params.size() = aSize;
RefPtr<SDBRequest> request = new SDBRequest(this);
rv = InitiateRequest(request, params);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
SDBConnection::Write(JS::HandleValue aValue,
JSContext* aCx,
nsISDBRequest** _retval)
{
AssertIsOnOwningThread();
nsresult rv = CheckState();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!mOpen) {
return NS_BASE_STREAM_CLOSED;
}
JS::Rooted<JS::Value> value(aCx, aValue);
nsCString data;
rv = GetWriteData(aCx, value, data);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
SDBRequestWriteParams params;
params.data() = data;
RefPtr<SDBRequest> request = new SDBRequest(this);
rv = InitiateRequest(request, params);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
SDBConnection::Close(nsISDBRequest** _retval)
{
AssertIsOnOwningThread();
nsresult rv = CheckState();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!mOpen) {
return NS_BASE_STREAM_CLOSED;
}
SDBRequestCloseParams params;
RefPtr<SDBRequest> request = new SDBRequest(this);
rv = InitiateRequest(request, params);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
SDBConnection::GetCloseCallback(nsISDBCloseCallback** aCloseCallback)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aCloseCallback);
NS_IF_ADDREF(*aCloseCallback = mCloseCallback);
return NS_OK;
}
NS_IMETHODIMP
SDBConnection::SetCloseCallback(nsISDBCloseCallback* aCloseCallback)
{
AssertIsOnOwningThread();
mCloseCallback = aCloseCallback;
return NS_OK;
}
} // namespace dom
} // namespace mozilla

View file

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_simpledb_SDBConnection_h
#define mozilla_dom_simpledb_SDBConnection_h
#include "nsAutoPtr.h"
#include "nsISDBConnection.h"
#include "nsTArray.h"
#define NS_SDBCONNECTION_CONTRACTID \
"@mozilla.org/dom/sdb-connection;1"
class nsISDBCloseCallback;
namespace mozilla {
namespace ipc {
class PBackgroundChild;
class PrincipalInfo;
} // namespace ipc
namespace dom {
class SDBConnectionChild;
class SDBRequest;
class SDBRequestParams;
class SDBConnection final
: public nsISDBConnection
{
typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
nsCOMPtr<nsISDBCloseCallback> mCloseCallback;
nsAutoPtr<PrincipalInfo> mPrincipalInfo;
SDBConnectionChild* mBackgroundActor;
bool mRunningRequest;
bool mOpen;
bool mAllowedToClose;
public:
static nsresult
Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
void
AssertIsOnOwningThread() const
{
NS_ASSERT_OWNINGTHREAD(SDBConnection);
}
void
ClearBackgroundActor();
void
OnNewRequest();
void
OnRequestFinished();
void
OnOpen();
void
OnClose(bool aAbnormal);
void
AllowToClose();
private:
SDBConnection();
~SDBConnection();
nsresult
CheckState();
nsresult
EnsureBackgroundActor();
nsresult
InitiateRequest(SDBRequest* aRequest,
const SDBRequestParams& aParams);
NS_DECL_ISUPPORTS
NS_DECL_NSISDBCONNECTION
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_simpledb_SDBConnection_h */

134
dom/simpledb/SDBRequest.cpp Normal file
View file

@ -0,0 +1,134 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SDBRequest.h"
#include "nsISDBCallbacks.h"
#include "nsThreadUtils.h"
#include "SDBConnection.h"
namespace mozilla {
namespace dom {
SDBRequest::SDBRequest(SDBConnection* aConnection)
: mConnection(aConnection)
, mResultCode(NS_OK)
, mHaveResultOrErrorCode(false)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aConnection);
}
SDBRequest::~SDBRequest()
{
AssertIsOnOwningThread();
}
void
SDBRequest::SetResult(nsIVariant* aResult)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aResult);
MOZ_ASSERT(mConnection);
MOZ_ASSERT(!mHaveResultOrErrorCode);
mResult = aResult;
mHaveResultOrErrorCode = true;
FireCallback();
}
void
SDBRequest::SetError(nsresult aRv)
{
AssertIsOnOwningThread();
MOZ_ASSERT(mConnection);
MOZ_ASSERT(mResultCode == NS_OK);
MOZ_ASSERT(!mHaveResultOrErrorCode);
mResultCode = aRv;
mHaveResultOrErrorCode = true;
FireCallback();
}
void
SDBRequest::FireCallback()
{
AssertIsOnOwningThread();
if (mCallback) {
nsCOMPtr<nsISDBCallback> callback;
callback.swap(mCallback);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(
NewRunnableMethod<RefPtr<SDBRequest>>(
"nsISDBCallback::OnComplete",
callback,
&nsISDBCallback::OnComplete,
this)));
}
}
NS_IMPL_CYCLE_COLLECTING_ADDREF(SDBRequest)
NS_IMPL_CYCLE_COLLECTING_RELEASE(SDBRequest)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SDBRequest)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsISDBRequest)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(SDBRequest, mCallback, mResult)
NS_IMETHODIMP
SDBRequest::GetResult(nsIVariant** aResult)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aResult);
if (!mHaveResultOrErrorCode) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_IF_ADDREF(*aResult = mResult);
return NS_OK;
}
NS_IMETHODIMP
SDBRequest::GetResultCode(nsresult* aResultCode)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aResultCode);
if (!mHaveResultOrErrorCode) {
return NS_ERROR_NOT_AVAILABLE;
}
*aResultCode = mResultCode;
return NS_OK;
}
NS_IMETHODIMP
SDBRequest::GetCallback(nsISDBCallback** aCallback)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aCallback);
NS_IF_ADDREF(*aCallback = mCallback);
return NS_OK;
}
NS_IMETHODIMP
SDBRequest::SetCallback(nsISDBCallback* aCallback)
{
AssertIsOnOwningThread();
mCallback = aCallback;
return NS_OK;
}
} // namespace dom
} // namespace mozilla

70
dom/simpledb/SDBRequest.h Normal file
View file

@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_simpledb_SDBRequest_h
#define mozilla_dom_simpledb_SDBRequest_h
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISDBRequest.h"
#include "nsIVariant.h"
class nsISDBCallback;
namespace mozilla {
namespace dom {
class SDBConnection;
class SDBRequest final
: public nsISDBRequest
{
RefPtr<SDBConnection> mConnection;
nsCOMPtr<nsIVariant> mResult;
nsCOMPtr<nsISDBCallback> mCallback;
nsresult mResultCode;
bool mHaveResultOrErrorCode;
public:
explicit SDBRequest(SDBConnection* aConnection);
void
AssertIsOnOwningThread() const
{
NS_ASSERT_OWNINGTHREAD(SDBRequest);
}
SDBConnection*
GetConnection() const
{
AssertIsOnOwningThread();
return mConnection;
}
void
SetResult(nsIVariant* aResult);
void
SetError(nsresult aRv);
private:
~SDBRequest();
void
FireCallback();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSISDBREQUEST
NS_DECL_CYCLE_COLLECTION_CLASS(SDBRequest)
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_simpledb_SDBRequest_h

View file

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SDBResults.h"
#include "nsContentUtils.h"
namespace mozilla {
namespace dom {
SDBResult::SDBResult(const nsACString& aData)
: mData(aData)
{
}
NS_IMPL_ISUPPORTS(SDBResult,
nsISDBResult)
NS_IMETHODIMP
SDBResult::GetAsArray(uint32_t* aDataLen, uint8_t** aData)
{
MOZ_ASSERT(aDataLen);
MOZ_ASSERT(aData);
if (mData.IsEmpty()) {
*aDataLen = 0;
*aData = nullptr;
return NS_OK;
}
uint32_t length = mData.Length();
uint8_t* data = static_cast<uint8_t*>(moz_xmalloc(length * sizeof(uint8_t)));
if (!data) {
return NS_ERROR_OUT_OF_MEMORY;
}
memcpy(data, mData.BeginReading(), length * sizeof(uint8_t));
*aDataLen = length;
*aData = data;
return NS_OK;
}
NS_IMETHODIMP
SDBResult::GetAsArrayBuffer(JSContext* aCx, JS::MutableHandleValue _retval)
{
JS::Rooted<JSObject*> arrayBuffer(aCx);
nsresult rv =
nsContentUtils::CreateArrayBuffer(aCx, mData, arrayBuffer.address());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
_retval.setObject(*arrayBuffer);
return NS_OK;
}
} // namespace dom
} // namespace mozilla

35
dom/simpledb/SDBResults.h Normal file
View file

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_simpledb_SDBResults_h
#define mozilla_dom_simpledb_SDBResults_h
#include "nsISDBResults.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
class SDBResult
: public nsISDBResult
{
nsCString mData;
public:
explicit SDBResult(const nsACString& aData);
private:
virtual ~SDBResult()
{ }
NS_DECL_ISUPPORTS
NS_DECL_NSISDBRESULT
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_simpledb_SDBResults_h

View file

@ -0,0 +1,15 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SimpleDBCommon.h"
namespace mozilla {
namespace dom {
const char* kPrefSimpleDBEnabled = "dom.simpleDB.enabled";
} // namespace dom
} // namespace mozilla

View file

@ -0,0 +1,18 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_simpledb_SimpledbCommon_h
#define mozilla_dom_simpledb_SimpledbCommon_h
namespace mozilla {
namespace dom {
extern const char* kPrefSimpleDBEnabled;
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_simpledb_SimpledbCommon_h

43
dom/simpledb/moz.build Normal file
View file

@ -0,0 +1,43 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'nsISDBCallbacks.idl',
'nsISDBConnection.idl',
'nsISDBRequest.idl',
'nsISDBResults.idl',
]
XPIDL_MODULE = 'dom_simpledb'
EXPORTS.mozilla.dom.simpledb += [
'ActorsParent.h',
]
EXPORTS.mozilla.dom += [
'SDBConnection.h',
]
UNIFIED_SOURCES += [
'ActorsChild.cpp',
'ActorsParent.cpp',
'SDBConnection.cpp',
'SDBRequest.cpp',
'SDBResults.cpp',
'SimpleDBCommon.cpp',
]
IPDL_SOURCES += [
'PBackgroundSDBConnection.ipdl',
'PBackgroundSDBRequest.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

View file

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsISDBConnection;
interface nsISDBRequest;
[scriptable, function, uuid(8cbd576c-c6bf-42fd-96ee-3b824dafe1d4)]
interface nsISDBCallback : nsISupports
{
void onComplete(in nsISDBRequest aRequest);
};
[scriptable, function, uuid(e0821d43-62b9-40fe-99f8-ff9ab3184cbf)]
interface nsISDBCloseCallback : nsISupports
{
void onClose(in nsISDBConnection aConnection);
};

View file

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIPrincipal;
interface nsISDBCloseCallback;
interface nsISDBRequest;
[scriptable, builtinclass, uuid(ea420fdd-548f-44f9-9286-59aad6a40f01)]
interface nsISDBConnection : nsISupports
{
[must_use] void
init(in nsIPrincipal aPrincipal);
[must_use] nsISDBRequest
open(in AString aName);
[must_use] nsISDBRequest
seek(in unsigned long long offset);
[must_use] nsISDBRequest
read(in unsigned long long size);
[must_use, implicit_jscontext] nsISDBRequest
write(in jsval value);
[must_use] nsISDBRequest
close();
attribute nsISDBCloseCallback closeCallback;
};

View file

@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsISDBCallback;
interface nsIVariant;
[scriptable, uuid(13f05bcf-715c-427e-aac8-df9b2c1ec1e3)]
interface nsISDBRequest : nsISupports
{
[must_use] readonly attribute nsIVariant result;
[must_use] readonly attribute nsresult resultCode;
attribute nsISDBCallback callback;
};

View file

@ -0,0 +1,18 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
[scriptable, uuid(bca19e01-b34e-4a48-8875-2f4cb871febf)]
interface nsISDBResult : nsISupports
{
[must_use] void
getAsArray([optional] out uint32_t dataLen,
[array, retval, size_is(dataLen)] out uint8_t data);
[must_use, implicit_jscontext] jsval
getAsArrayBuffer();
};

View file

@ -16,6 +16,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/dom/ClientManagerActors.h"
#include "mozilla/dom/PBackgroundSDBConnectionChild.h"
#include "mozilla/dom/PFileSystemRequestChild.h"
#include "mozilla/dom/FileSystemTaskBase.h"
#include "mozilla/dom/asmjscache/AsmJSCache.h"
@ -239,6 +240,24 @@ BackgroundChildImpl::DeallocPBackgroundLocalStorageCacheChild(
return true;
}
BackgroundChildImpl::PBackgroundSDBConnectionChild*
BackgroundChildImpl::AllocPBackgroundSDBConnectionChild(
const PrincipalInfo& aPrincipalInfo)
{
MOZ_CRASH("PBackgroundSDBConnectionChild actor should be manually "
"constructed!");
}
bool
BackgroundChildImpl::DeallocPBackgroundSDBConnectionChild(
PBackgroundSDBConnectionChild* aActor)
{
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
BackgroundChildImpl::PBackgroundStorageChild*
BackgroundChildImpl::AllocPBackgroundStorageChild(const nsString& aProfilePath)
{

View file

@ -70,6 +70,14 @@ protected:
DeallocPBackgroundIndexedDBUtilsChild(PBackgroundIndexedDBUtilsChild* aActor)
override;
virtual PBackgroundSDBConnectionChild*
AllocPBackgroundSDBConnectionChild(const PrincipalInfo& aPrincipalInfo)
override;
virtual bool
DeallocPBackgroundSDBConnectionChild(PBackgroundSDBConnectionChild* aActor)
override;
virtual PBackgroundLocalStorageCacheChild*
AllocPBackgroundLocalStorageCacheChild(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,

View file

@ -34,6 +34,7 @@
#include "mozilla/dom/ipc/PendingIPCBlobParent.h"
#include "mozilla/dom/ipc/TemporaryIPCBlobParent.h"
#include "mozilla/dom/quota/ActorsParent.h"
#include "mozilla/dom/simpledb/ActorsParent.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/dom/MIDIManagerParent.h"
#include "mozilla/dom/MIDIPortParent.h"
@ -252,6 +253,43 @@ BackgroundParentImpl::RecvFlushPendingFileDeletions()
return IPC_OK();
}
BackgroundParentImpl::PBackgroundSDBConnectionParent*
BackgroundParentImpl::AllocPBackgroundSDBConnectionParent(
const PrincipalInfo& aPrincipalInfo)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
return mozilla::dom::AllocPBackgroundSDBConnectionParent(aPrincipalInfo);
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPBackgroundSDBConnectionConstructor(
PBackgroundSDBConnectionParent* aActor,
const PrincipalInfo& aPrincipalInfo)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
if (!mozilla::dom::RecvPBackgroundSDBConnectionConstructor(aActor,
aPrincipalInfo)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
bool
BackgroundParentImpl::DeallocPBackgroundSDBConnectionParent(
PBackgroundSDBConnectionParent* aActor)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
return mozilla::dom::DeallocPBackgroundSDBConnectionParent(aActor);
}
BackgroundParentImpl::PBackgroundLocalStorageCacheParent*
BackgroundParentImpl::AllocPBackgroundLocalStorageCacheParent(
const PrincipalInfo& aPrincipalInfo,

View file

@ -63,6 +63,20 @@ protected:
virtual mozilla::ipc::IPCResult
RecvFlushPendingFileDeletions() override;
virtual PBackgroundSDBConnectionParent*
AllocPBackgroundSDBConnectionParent(const PrincipalInfo& aPrincipalInfo)
override;
virtual mozilla::ipc::IPCResult
RecvPBackgroundSDBConnectionConstructor(
PBackgroundSDBConnectionParent* aActor,
const PrincipalInfo& aPrincipalInfo)
override;
virtual bool
DeallocPBackgroundSDBConnectionParent(PBackgroundSDBConnectionParent* aActor)
override;
virtual PBackgroundLocalStorageCacheParent*
AllocPBackgroundLocalStorageCacheParent(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,

View file

@ -5,6 +5,7 @@
include protocol PAsmJSCacheEntry;
include protocol PBackgroundIDBFactory;
include protocol PBackgroundIndexedDBUtils;
include protocol PBackgroundSDBConnection;
include protocol PBackgroundLocalStorageCache;
include protocol PBackgroundStorage;
include protocol PBackgroundTest;
@ -66,6 +67,7 @@ sync protocol PBackground
manages PAsmJSCacheEntry;
manages PBackgroundIDBFactory;
manages PBackgroundIndexedDBUtils;
manages PBackgroundSDBConnection;
manages PBackgroundLocalStorageCache;
manages PBackgroundStorage;
manages PBackgroundTest;
@ -108,6 +110,8 @@ parent:
// Use only for testing!
async FlushPendingFileDeletions();
async PBackgroundSDBConnection(PrincipalInfo principalInfo);
async PBackgroundLocalStorageCache(PrincipalInfo principalInfo,
nsCString originKey,
uint32_t privateBrowsingId);

View file

@ -20,8 +20,6 @@
namespace js {
#ifdef JS_CRASH_DIAGNOSTICS
class CompartmentChecker
{
JS::Compartment* compartment;
@ -175,8 +173,6 @@ class CompartmentChecker
}
};
#endif // JS_CRASH_DIAGNOSTICS
/*
* Don't perform these checks when called from a finalizer. The checking
* depends on other objects not having been swept yet.

View file

@ -40,9 +40,7 @@ NS_DEFINE_NAMED_CID(MOZ_JSSUBSCRIPTLOADER_CID);
{ &kMOZ_JSSUBSCRIPTLOADER_CID, false, nullptr, mozJSSubScriptLoaderConstructor },
#define XPCONNECT_CONTRACTS \
{ XPC_ID_CONTRACTID, &kNS_JS_ID_CID }, \
{ XPC_XPCONNECT_CONTRACTID, &kNS_XPCONNECT_CID }, \
{ XPC_CONTEXT_STACK_CONTRACTID, &kNS_XPCONNECT_CID }, \
{ MOZJSCOMPONENTLOADER_CONTRACTID, &kMOZJSCOMPONENTLOADER_CID }, \
{ MOZJSSUBSCRIPTLOADER_CONTRACTID, &kMOZ_JSSUBSCRIPTLOADER_CID },

View file

@ -56,11 +56,9 @@ bool nsXPConnect::gOnceAliveNowDead = false;
nsIScriptSecurityManager* nsXPConnect::gScriptSecurityManager = nullptr;
nsIPrincipal* nsXPConnect::gSystemPrincipal = nullptr;
const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1";
const char XPC_EXCEPTION_CONTRACTID[] = "@mozilla.org/js/xpc/Exception;1";
const char XPC_CONSOLE_CONTRACTID[] = "@mozilla.org/consoleservice;1";
const char XPC_SCRIPT_ERROR_CONTRACTID[] = "@mozilla.org/scripterror;1";
const char XPC_ID_CONTRACTID[] = "@mozilla.org/js/xpc/ID;1";
const char XPC_XPCONNECT_CONTRACTID[] = "@mozilla.org/js/xpc/XPConnect;1";
/***************************************************************************/

View file

@ -182,11 +182,9 @@ class Exception;
/***************************************************************************/
// data declarations...
extern const char XPC_CONTEXT_STACK_CONTRACTID[];
extern const char XPC_EXCEPTION_CONTRACTID[];
extern const char XPC_CONSOLE_CONTRACTID[];
extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
extern const char XPC_ID_CONTRACTID[];
extern const char XPC_XPCONNECT_CONTRACTID[];
/***************************************************************************/

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<meta charset="utf-8">
<script type="text/javascript">
function start()
{
var input = document.querySelector("input");
input.value = '\u{1f468}\u{200d}\u{1f469}\u{200d}\u{1f467}\u{200d}\u{1f466}';
input.addEventListener("focus", () => {
input.setSelectionRange(input.value.length, input.value.length);
document.documentElement.removeAttribute("class");
});
input.focus();
}
</script>
</head>
<body onload="start()">
<input type="text"></input>
</body>
</html>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript">
function start()
{
var input = document.querySelector("input");
input.value = '\u{1f468}\u{200d}\u{1f469}\u{200d}\u{1f467}\u{200d}\u{1f466}';
input.addEventListener("focus", () => {
input.setSelectionRange(0, 0);
synthesizeKey("KEY_ArrowRight");
document.documentElement.removeAttribute("class");
});
input.focus();
}
</script>
</head>
<body onload="start()">
<input type="text"></input>
</body>
</html>

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<meta charset="utf-8">
<script type="text/javascript">
function start()
{
var input = document.querySelector("input");
input.value = '\u{1f468}\u{200d}\u{1f469}\u{200d}\u{1f467}\u{200d}\u{1f466}';
input.addEventListener("focus", () => {
input.setSelectionRange(0, 0);
document.documentElement.removeAttribute("class");
});
input.focus();
}
</script>
</head>
<body onload="start()">
<input type="text"></input>
</body>
</html>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript">
function start()
{
var input = document.querySelector("input");
input.value = '\u{1f468}\u{200d}\u{1f469}\u{200d}\u{1f467}\u{200d}\u{1f466}';
input.addEventListener("focus", () => {
input.setSelectionRange(input.value.length, input.value.length);
synthesizeKey("KEY_ArrowLeft");
document.documentElement.removeAttribute("class");
});
input.focus();
}
</script>
</head>
<body onload="start()">
<input type="text"></input>
</body>
</html>

View file

@ -317,6 +317,10 @@ support-files =
bug1423331-2-ref.html
bug1423331-3.html
bug1423331-4.html
bug1484094-1.html
bug1484094-1-ref.html
bug1484094-2.html
bug1484094-2-ref.html
image_rgrg-256x256.png
input-invalid-ref.html
input-maxlength-invalid-change.html

View file

@ -199,6 +199,8 @@ var tests = [
// FIXME(bug 1434949): These two fail in some platforms.
// [ 'bug1423331-3.html' , 'bug1423331-1-ref.html' ] ,
// [ 'bug1423331-4.html' , 'bug1423331-2-ref.html' ] ,
[ 'bug1484094-1.html' , 'bug1484094-1-ref.html' ] ,
[ 'bug1484094-2.html' , 'bug1484094-2-ref.html' ] ,
function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled']]}, nextTest);} ,
];

View file

@ -31,6 +31,10 @@
#define NS_CANVASRENDERINGCONTEXTWEBGL_CID \
{ 0x2fe88332, 0x31c6, 0x4829, { 0xb2, 0x47, 0xa0, 0x7d, 0x8a, 0x7e, 0xe8, 0x0fe } }
// {ae2793c0-2ba3-4adb-9c5e-c23525812c64}
#define NS_SDBCONNECTION_CID \
{ 0xae2793c0, 0x2ba3, 0x4adb, { 0x9c, 0x5e, 0xc2, 0x35, 0x25, 0x81, 0x2c, 0x64 } }
// {A746DECD-AE74-4d86-8E75-4FDA81A9BE90}
#define NS_DOMSESSIONSTORAGEMANAGER_CID \
{ 0xa746decd, 0xae74, 0x4d86, { 0x8e, 0x75, 0x4f, 0xda, 0x81, 0xa9, 0xbe, 0x90 } }

View file

@ -66,6 +66,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/dom/BlobURL.h"
#include "mozilla/dom/DOMRequest.h"
#include "mozilla/dom/SDBConnection.h"
#include "mozilla/dom/LocalStorageManager.h"
#include "mozilla/dom/network/UDPSocketChild.h"
#include "mozilla/dom/quota/QuotaManagerService.h"
@ -534,6 +535,7 @@ NS_DEFINE_NAMED_CID(NS_VIDEODOCUMENT_CID);
NS_DEFINE_NAMED_CID(NS_STYLESHEETSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURI_CID);
NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURIMUTATOR_CID);
NS_DEFINE_NAMED_CID(NS_SDBCONNECTION_CID);
NS_DEFINE_NAMED_CID(NS_DOMSESSIONSTORAGEMANAGER_CID);
NS_DEFINE_NAMED_CID(NS_DOMLOCALSTORAGEMANAGER_CID);
NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID);
@ -771,6 +773,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_STYLESHEETSERVICE_CID, false, nullptr, nsStyleSheetServiceConstructor },
{ &kNS_HOSTOBJECTURI_CID, false, nullptr, BlobURLMutatorConstructor }, // do_CreateInstance returns mutator
{ &kNS_HOSTOBJECTURIMUTATOR_CID, false, nullptr, BlobURLMutatorConstructor },
{ &kNS_SDBCONNECTION_CID, false, nullptr, SDBConnection::Create },
{ &kNS_DOMSESSIONSTORAGEMANAGER_CID, false, nullptr, SessionStorageManagerConstructor },
{ &kNS_DOMLOCALSTORAGEMANAGER_CID, false, nullptr, LocalStorageManagerConstructor },
{ &kNS_TEXTEDITOR_CID, false, nullptr, TextEditorConstructor },
@ -871,6 +874,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ NS_WINDOWCONTROLLER_CONTRACTID, &kNS_WINDOWCONTROLLER_CID },
{ PLUGIN_DLF_CONTRACTID, &kNS_PLUGINDOCLOADERFACTORY_CID },
{ NS_STYLESHEETSERVICE_CONTRACTID, &kNS_STYLESHEETSERVICE_CID },
{ NS_SDBCONNECTION_CONTRACTID, &kNS_SDBCONNECTION_CID },
{ "@mozilla.org/dom/localStorage-manager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },
// Keeping the old ContractID for backward compatibility
{ "@mozilla.org/dom/storagemanager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },

View file

@ -7994,8 +7994,8 @@ IsAcceptableCaretPosition(const gfxSkipCharsIterator& aIter,
return false;
if (index > 0) {
// Check whether the proposed position is in between the two halves of a
// surrogate pair, or before a Variation Selector character;
// if so, this is not a valid character boundary.
// surrogate pair, before a Variation Selector character, or within a
// ligated emoji sequence; if so, this is not a valid character boundary.
// (In the case where we are respecting clusters, we won't actually get
// this far because the low surrogate is also marked as non-clusterStart
// so we'll return FALSE above.)
@ -8005,7 +8005,9 @@ IsAcceptableCaretPosition(const gfxSkipCharsIterator& aIter,
if (gfxFontUtils::IsVarSelector(ch) ||
(NS_IS_LOW_SURROGATE(ch) && offs > 0 &&
NS_IS_HIGH_SURROGATE(frag->CharAt(offs - 1)))) {
NS_IS_HIGH_SURROGATE(frag->CharAt(offs - 1))) ||
(!aTextRun->IsLigatureGroupStart(index) &&
unicode::GetEmojiPresentation(ch) == unicode::EmojiDefault)) {
return false;
}
@ -8016,11 +8018,12 @@ IsAcceptableCaretPosition(const gfxSkipCharsIterator& aIter,
if (NS_IS_LOW_SURROGATE(ch2)) {
ch = SURROGATE_TO_UCS4(ch, ch2);
// If the character is a (Plane-14) variation selector,
// or a Regional Indicator character that is ligated with the previous
// character, this is not a valid boundary.
// or an emoji character that is ligated with the previous
// character (i.e. part of a Regional-Indicator flag pair,
// or an emoji-ZWJ sequence), this is not a valid boundary.
if (gfxFontUtils::IsVarSelector(ch) ||
(gfxFontUtils::IsRegionalIndicator(ch) &&
!aTextRun->IsLigatureGroupStart(index))) {
(!aTextRun->IsLigatureGroupStart(index) &&
unicode::GetEmojiPresentation(ch) == unicode::EmojiDefault)) {
return false;
}
}