forked from mirrors/gecko-dev
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
commit
39fac07af8
69 changed files with 4492 additions and 361 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
8
dom/cache/FileUtils.cpp
vendored
8
dom/cache/FileUtils.cpp
vendored
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ DIRS += [
|
|||
'payments',
|
||||
'websocket',
|
||||
'serviceworkers',
|
||||
'simpledb',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,6 @@ struct IPCPaymentDetails
|
|||
IPCPaymentDetailsModifier[] modifiers;
|
||||
nsString error;
|
||||
nsString shippingAddressErrors;
|
||||
bool displayItemsPassed;
|
||||
bool shippingOptionsPassed;
|
||||
bool modifiersPassed;
|
||||
};
|
||||
|
||||
struct IPCPaymentOptions
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
100
dom/quota/MemoryOutputStream.cpp
Normal file
100
dom/quota/MemoryOutputStream.cpp
Normal 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
|
||||
58
dom/quota/MemoryOutputStream.h
Normal file
58
dom/quota/MemoryOutputStream.h
Normal 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 */
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
#include "nsIQuotaRequests.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
using namespace mozilla::dom::quota;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
50
dom/quota/test/browser_simpledb.js
Normal file
50
dom/quota/test/browser_simpledb.js
Normal 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);
|
||||
});
|
||||
37
dom/quota/test/head-shared.js
Normal file
37
dom/quota/test/head-shared.js
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
19
dom/quota/test/test_simpledb.html
Normal file
19
dom/quota/test/test_simpledb.html
Normal 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>
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
55
dom/quota/test/unit/test_simpledb.js
Normal file
55
dom/quota/test/unit/test_simpledb.js
Normal 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();
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
243
dom/simpledb/ActorsChild.cpp
Normal file
243
dom/simpledb/ActorsChild.cpp
Normal 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
115
dom/simpledb/ActorsChild.h
Normal 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
|
||||
2010
dom/simpledb/ActorsParent.cpp
Normal file
2010
dom/simpledb/ActorsParent.cpp
Normal file
File diff suppressed because it is too large
Load diff
52
dom/simpledb/ActorsParent.h
Normal file
52
dom/simpledb/ActorsParent.h
Normal 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
|
||||
64
dom/simpledb/PBackgroundSDBConnection.ipdl
Normal file
64
dom/simpledb/PBackgroundSDBConnection.ipdl
Normal 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
|
||||
50
dom/simpledb/PBackgroundSDBRequest.ipdl
Normal file
50
dom/simpledb/PBackgroundSDBRequest.ipdl
Normal 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
|
||||
428
dom/simpledb/SDBConnection.cpp
Normal file
428
dom/simpledb/SDBConnection.cpp
Normal 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
|
||||
100
dom/simpledb/SDBConnection.h
Normal file
100
dom/simpledb/SDBConnection.h
Normal 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
134
dom/simpledb/SDBRequest.cpp
Normal 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
70
dom/simpledb/SDBRequest.h
Normal 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
|
||||
63
dom/simpledb/SDBResults.cpp
Normal file
63
dom/simpledb/SDBResults.cpp
Normal 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
35
dom/simpledb/SDBResults.h
Normal 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
|
||||
15
dom/simpledb/SimpleDBCommon.cpp
Normal file
15
dom/simpledb/SimpleDBCommon.cpp
Normal 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
|
||||
18
dom/simpledb/SimpleDBCommon.h
Normal file
18
dom/simpledb/SimpleDBCommon.h
Normal 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
43
dom/simpledb/moz.build
Normal 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']
|
||||
22
dom/simpledb/nsISDBCallbacks.idl
Normal file
22
dom/simpledb/nsISDBCallbacks.idl
Normal 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);
|
||||
};
|
||||
35
dom/simpledb/nsISDBConnection.idl
Normal file
35
dom/simpledb/nsISDBConnection.idl
Normal 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;
|
||||
};
|
||||
20
dom/simpledb/nsISDBRequest.idl
Normal file
20
dom/simpledb/nsISDBRequest.idl
Normal 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;
|
||||
};
|
||||
18
dom/simpledb/nsISDBResults.idl
Normal file
18
dom/simpledb/nsISDBResults.idl
Normal 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();
|
||||
};
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
|||
21
layout/base/tests/bug1484094-1-ref.html
Normal file
21
layout/base/tests/bug1484094-1-ref.html
Normal 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>
|
||||
23
layout/base/tests/bug1484094-1.html
Normal file
23
layout/base/tests/bug1484094-1.html
Normal 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>
|
||||
21
layout/base/tests/bug1484094-2-ref.html
Normal file
21
layout/base/tests/bug1484094-2-ref.html
Normal 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>
|
||||
23
layout/base/tests/bug1484094-2.html
Normal file
23
layout/base/tests/bug1484094-2.html
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);} ,
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -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 } }
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue