зеркало из https://github.com/mozilla/gecko-dev.git
Bug 809661 - Need a speedy way to construct a thread list for SMS messages. r=sicking, a=blocking-basecamp
This commit is contained in:
Родитель
84f9d5d059
Коммит
6910d3c122
|
@ -11,7 +11,7 @@ relativesrcdir = @relativesrcdir@
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
PARALLEL_DIRS = interfaces src
|
DIRS = interfaces src
|
||||||
|
|
||||||
TEST_DIRS += tests
|
TEST_DIRS += tests
|
||||||
ifdef ENABLE_TESTS
|
ifdef ENABLE_TESTS
|
||||||
|
|
|
@ -8,7 +8,7 @@ interface nsIDOMEventListener;
|
||||||
interface nsIDOMMozSmsRequest;
|
interface nsIDOMMozSmsRequest;
|
||||||
interface nsIDOMMozSmsFilter;
|
interface nsIDOMMozSmsFilter;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(1bee1224-56a2-4935-af7b-0011746306cb)]
|
[scriptable, builtinclass, uuid(caaf5c38-a730-4dbb-a0f0-12384bfac8e3)]
|
||||||
interface nsIDOMMozSmsManager : nsIDOMEventTarget
|
interface nsIDOMMozSmsManager : nsIDOMEventTarget
|
||||||
{
|
{
|
||||||
unsigned short getNumberOfMessagesForText(in DOMString text);
|
unsigned short getNumberOfMessagesForText(in DOMString text);
|
||||||
|
@ -29,6 +29,8 @@ interface nsIDOMMozSmsManager : nsIDOMEventTarget
|
||||||
|
|
||||||
nsIDOMMozSmsRequest markMessageRead(in long id, in boolean aValue);
|
nsIDOMMozSmsRequest markMessageRead(in long id, in boolean aValue);
|
||||||
|
|
||||||
|
nsIDOMMozSmsRequest getThreadList();
|
||||||
|
|
||||||
[implicit_jscontext] attribute jsval onreceived;
|
[implicit_jscontext] attribute jsval onreceived;
|
||||||
[implicit_jscontext] attribute jsval onsent;
|
[implicit_jscontext] attribute jsval onsent;
|
||||||
[implicit_jscontext] attribute jsval ondeliverysuccess;
|
[implicit_jscontext] attribute jsval ondeliverysuccess;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
interface nsIDOMMozSmsFilter;
|
interface nsIDOMMozSmsFilter;
|
||||||
interface nsISmsRequest;
|
interface nsISmsRequest;
|
||||||
|
|
||||||
[scriptable, uuid(6ad55465-6937-4491-93ca-29dad9775d46)]
|
[scriptable, uuid(c2cb2af7-6b96-4915-bcc8-54ad705d6110)]
|
||||||
interface nsISmsDatabaseService : nsISupports
|
interface nsISmsDatabaseService : nsISupports
|
||||||
{
|
{
|
||||||
// Takes some information required to save the message and returns its id.
|
// Takes some information required to save the message and returns its id.
|
||||||
|
@ -30,4 +30,6 @@ interface nsISmsDatabaseService : nsISupports
|
||||||
void getNextMessageInList(in long listId, in nsISmsRequest request);
|
void getNextMessageInList(in long listId, in nsISmsRequest request);
|
||||||
void clearMessageList(in long listId);
|
void clearMessageList(in long listId);
|
||||||
void markMessageRead(in long messageId, in boolean value, in nsISmsRequest request);
|
void markMessageRead(in long messageId, in boolean value, in nsISmsRequest request);
|
||||||
|
|
||||||
|
void getThreadList(in nsISmsRequest request);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,15 @@
|
||||||
|
|
||||||
interface nsIDOMMozSmsMessage;
|
interface nsIDOMMozSmsMessage;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(97067327-64b9-4e26-848b-59e443c55db9)]
|
dictionary SmsThreadListItem
|
||||||
|
{
|
||||||
|
DOMString senderOrReceiver;
|
||||||
|
unsigned long long timestamp;
|
||||||
|
DOMString body;
|
||||||
|
unsigned long long unreadCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(82a6d16d-cf33-4745-8662-8b5d441f512f)]
|
||||||
interface nsISmsRequest : nsISupports
|
interface nsISmsRequest : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -37,4 +45,8 @@ interface nsISmsRequest : nsISupports
|
||||||
|
|
||||||
void notifyMessageMarkedRead(in boolean read);
|
void notifyMessageMarkedRead(in boolean read);
|
||||||
void notifyMarkMessageReadFailed(in long error);
|
void notifyMarkMessageReadFailed(in long error);
|
||||||
|
|
||||||
|
[implicit_jscontext]
|
||||||
|
void notifyThreadList(in jsval threadList);
|
||||||
|
void notifyThreadListFailed(in long error);
|
||||||
};
|
};
|
||||||
|
|
|
@ -303,6 +303,20 @@ SmsManager::MarkMessageRead(int32_t aId, bool aValue,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SmsManager::GetThreadList(nsIDOMMozSmsRequest** aRequest)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMMozSmsRequest> req = SmsRequest::Create(this);
|
||||||
|
nsCOMPtr<nsISmsDatabaseService> smsDBService =
|
||||||
|
do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(smsDBService, NS_ERROR_FAILURE);
|
||||||
|
nsCOMPtr<nsISmsRequest> forwarder =
|
||||||
|
new SmsRequestForwarder(static_cast<SmsRequest*>(req.get()));
|
||||||
|
smsDBService->GetThreadList(forwarder);
|
||||||
|
req.forget(aRequest);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SmsManager::DispatchTrustedSmsEventToSelf(const nsAString& aEventName, nsIDOMMozSmsMessage* aMessage)
|
SmsManager::DispatchTrustedSmsEventToSelf(const nsAString& aEventName, nsIDOMMozSmsMessage* aMessage)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,11 +9,16 @@
|
||||||
#include "nsDOMString.h"
|
#include "nsDOMString.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsIDOMSmsMessage.h"
|
#include "nsIDOMSmsMessage.h"
|
||||||
|
#include "nsIScriptGlobalObject.h"
|
||||||
|
#include "nsPIDOMWindow.h"
|
||||||
#include "SmsCursor.h"
|
#include "SmsCursor.h"
|
||||||
#include "SmsMessage.h"
|
#include "SmsMessage.h"
|
||||||
#include "SmsManager.h"
|
#include "SmsManager.h"
|
||||||
#include "mozilla/dom/DOMError.h"
|
#include "mozilla/dom/DOMError.h"
|
||||||
#include "SmsParent.h"
|
#include "SmsParent.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "DictionaryHelpers.h"
|
||||||
|
#include "xpcpublic.h"
|
||||||
|
|
||||||
#define SUCCESS_EVENT_NAME NS_LITERAL_STRING("success")
|
#define SUCCESS_EVENT_NAME NS_LITERAL_STRING("success")
|
||||||
#define ERROR_EVENT_NAME NS_LITERAL_STRING("error")
|
#define ERROR_EVENT_NAME NS_LITERAL_STRING("error")
|
||||||
|
@ -145,12 +150,7 @@ SmsRequest::SetSuccess(nsIDOMMozSmsMessage* aMessage)
|
||||||
void
|
void
|
||||||
SmsRequest::SetSuccess(bool aResult)
|
SmsRequest::SetSuccess(bool aResult)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!");
|
SetSuccess(aResult ? JSVAL_TRUE : JSVAL_FALSE);
|
||||||
NS_PRECONDITION(!mError, "mError shouldn't have been set!");
|
|
||||||
NS_PRECONDITION(mResult == JSVAL_NULL, "mResult shouldn't have been set!");
|
|
||||||
|
|
||||||
mResult.setBoolean(aResult);
|
|
||||||
mDone = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -168,6 +168,17 @@ SmsRequest::SetSuccess(nsIDOMMozSmsCursor* aCursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SmsRequest::SetSuccess(const jsval& aResult)
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!");
|
||||||
|
NS_PRECONDITION(!mError, "mError shouldn't have been set!");
|
||||||
|
NS_PRECONDITION(JSVAL_IS_VOID(mResult), "mResult shouldn't have been set!");
|
||||||
|
|
||||||
|
mResult = aResult;
|
||||||
|
mDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SmsRequest::SetSuccessInternal(nsISupports* aObject)
|
SmsRequest::SetSuccessInternal(nsISupports* aObject)
|
||||||
{
|
{
|
||||||
|
@ -445,6 +456,134 @@ SmsRequest::NotifyMarkMessageReadFailed(int32_t aError)
|
||||||
return NotifyError(aError);
|
return NotifyError(aError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SmsRequest::NotifyThreadList(const jsval& aThreadList, JSContext* aCx)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aThreadList.isObject());
|
||||||
|
|
||||||
|
if (mParent) {
|
||||||
|
JSObject* array = const_cast<JSObject*>(&aThreadList.toObject());
|
||||||
|
|
||||||
|
uint32_t length;
|
||||||
|
bool ok = JS_GetArrayLength(aCx, array, &length);
|
||||||
|
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
ReplyThreadList reply;
|
||||||
|
InfallibleTArray<ThreadListItem>& ipcItems = reply.items();
|
||||||
|
|
||||||
|
if (length) {
|
||||||
|
ipcItems.SetCapacity(length);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
|
jsval arrayEntry;
|
||||||
|
ok = JS_GetElement(aCx, array, i, &arrayEntry);
|
||||||
|
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
MOZ_ASSERT(arrayEntry.isObject());
|
||||||
|
|
||||||
|
SmsThreadListItem item;
|
||||||
|
nsresult rv = item.Init(aCx, &arrayEntry);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
ThreadListItem* ipcItem = ipcItems.AppendElement();
|
||||||
|
ipcItem->senderOrReceiver() = item.senderOrReceiver;
|
||||||
|
ipcItem->timestamp() = item.timestamp;
|
||||||
|
ipcItem->body() = item.body;
|
||||||
|
ipcItem->unreadCount() = item.unreadCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SendMessageReply(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NotifySuccess(aThreadList);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SmsRequest::NotifyThreadListFailed(int32_t aError)
|
||||||
|
{
|
||||||
|
if (mParent) {
|
||||||
|
return SendMessageReply(MessageReply(ReplyThreadListFail(aError)));
|
||||||
|
}
|
||||||
|
return NotifyError(aError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SmsRequest::NotifyThreadList(const InfallibleTArray<ThreadListItem>& aItems)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mParent);
|
||||||
|
MOZ_ASSERT(GetOwner());
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
NS_ENSURE_TRUE_VOID(sc);
|
||||||
|
|
||||||
|
JSContext* cx = sc->GetNativeContext();
|
||||||
|
MOZ_ASSERT(cx);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(GetOwner());
|
||||||
|
|
||||||
|
JSObject* ownerObj = sgo->GetGlobalJSObject();
|
||||||
|
NS_ENSURE_TRUE_VOID(ownerObj);
|
||||||
|
|
||||||
|
nsCxPusher pusher;
|
||||||
|
NS_ENSURE_TRUE_VOID(pusher.Push(cx, false));
|
||||||
|
|
||||||
|
JSAutoRequest ar(cx);
|
||||||
|
JSAutoCompartment ac(cx, ownerObj);
|
||||||
|
|
||||||
|
JSObject* array = JS_NewArrayObject(cx, aItems.Length(), nullptr);
|
||||||
|
NS_ENSURE_TRUE_VOID(array);
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < aItems.Length(); i++) {
|
||||||
|
const ThreadListItem& source = aItems[i];
|
||||||
|
|
||||||
|
nsString temp = source.senderOrReceiver();
|
||||||
|
|
||||||
|
jsval senderOrReceiver;
|
||||||
|
ok = xpc::StringToJsval(cx, temp, &senderOrReceiver);
|
||||||
|
NS_ENSURE_TRUE_VOID(ok);
|
||||||
|
|
||||||
|
JSObject* timestampObj = JS_NewDateObjectMsec(cx, source.timestamp());
|
||||||
|
NS_ENSURE_TRUE_VOID(timestampObj);
|
||||||
|
|
||||||
|
jsval timestamp = OBJECT_TO_JSVAL(timestampObj);
|
||||||
|
|
||||||
|
temp = source.body();
|
||||||
|
|
||||||
|
jsval body;
|
||||||
|
ok = xpc::StringToJsval(cx, temp, &body);
|
||||||
|
NS_ENSURE_TRUE_VOID(ok);
|
||||||
|
|
||||||
|
jsval unreadCount = JS_NumberValue(double(source.unreadCount()));
|
||||||
|
|
||||||
|
JSObject* elementObj = JS_NewObject(cx, nullptr, nullptr, nullptr);
|
||||||
|
NS_ENSURE_TRUE_VOID(elementObj);
|
||||||
|
|
||||||
|
ok = JS_SetProperty(cx, elementObj, "senderOrReceiver", &senderOrReceiver);
|
||||||
|
NS_ENSURE_TRUE_VOID(ok);
|
||||||
|
|
||||||
|
ok = JS_SetProperty(cx, elementObj, "timestamp", ×tamp);
|
||||||
|
NS_ENSURE_TRUE_VOID(ok);
|
||||||
|
|
||||||
|
ok = JS_SetProperty(cx, elementObj, "body", &body);
|
||||||
|
NS_ENSURE_TRUE_VOID(ok);
|
||||||
|
|
||||||
|
ok = JS_SetProperty(cx, elementObj, "unreadCount", &unreadCount);
|
||||||
|
NS_ENSURE_TRUE_VOID(ok);
|
||||||
|
|
||||||
|
jsval element = OBJECT_TO_JSVAL(elementObj);
|
||||||
|
|
||||||
|
ok = JS_SetElement(cx, array, i, &element);
|
||||||
|
NS_ENSURE_TRUE_VOID(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifyThreadList(OBJECT_TO_JSVAL(array), cx);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sms
|
} // namespace sms
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -17,24 +17,33 @@ namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
namespace sms {
|
namespace sms {
|
||||||
|
|
||||||
|
class SmsRequestChild;
|
||||||
class SmsRequestParent;
|
class SmsRequestParent;
|
||||||
class MessageReply;
|
class MessageReply;
|
||||||
|
class ThreadListItem;
|
||||||
|
|
||||||
// We need this forwarder to avoid a QI to nsIClassInfo.
|
// We need this forwarder to avoid a QI to nsIClassInfo.
|
||||||
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=775997#c51
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=775997#c51
|
||||||
class SmsRequestForwarder : public nsISmsRequest
|
class SmsRequestForwarder : public nsISmsRequest
|
||||||
{
|
{
|
||||||
NS_FORWARD_NSISMSREQUEST(mRealRequest->)
|
friend class SmsRequestChild;
|
||||||
|
|
||||||
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_FORWARD_NSISMSREQUEST(mRealRequest->)
|
||||||
|
|
||||||
SmsRequestForwarder(nsISmsRequest* aRealRequest) {
|
SmsRequestForwarder(nsISmsRequest* aRealRequest) {
|
||||||
mRealRequest = aRealRequest;
|
mRealRequest = aRealRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
virtual
|
virtual
|
||||||
~SmsRequestForwarder() {}
|
~SmsRequestForwarder() {}
|
||||||
|
|
||||||
private:
|
nsISmsRequest* GetRealRequest() {
|
||||||
|
return mRealRequest;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsISmsRequest> mRealRequest;
|
nsCOMPtr<nsISmsRequest> mRealRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,6 +75,9 @@ public:
|
||||||
mParentAlive = false;
|
mParentAlive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NotifyThreadList(const InfallibleTArray<ThreadListItem>& aItems);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SmsRequest() MOZ_DELETE;
|
SmsRequest() MOZ_DELETE;
|
||||||
|
|
||||||
|
@ -100,6 +112,11 @@ private:
|
||||||
*/
|
*/
|
||||||
void SetSuccess(nsIDOMMozSmsCursor* aCursor);
|
void SetSuccess(nsIDOMMozSmsCursor* aCursor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the object in a success state with the result being the given jsval.
|
||||||
|
*/
|
||||||
|
void SetSuccess(const jsval& aVal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the object in an error state with the error type being aError.
|
* Set the object in an error state with the error type being aError.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -112,6 +112,13 @@ SmsDatabaseService::MarkMessageRead(int32_t aMessageId, bool aValue,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SmsDatabaseService::GetThreadList(nsISmsRequest* aRequest)
|
||||||
|
{
|
||||||
|
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sms
|
} // namespace sms
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -90,6 +90,13 @@ SmsDatabaseService::MarkMessageRead(int32_t aMessageId,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SmsDatabaseService::GetThreadList(nsISmsRequest* aRequest)
|
||||||
|
{
|
||||||
|
NS_ERROR("We should not be here!");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sms
|
} // namespace sms
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -53,6 +53,10 @@ struct MarkMessageReadRequest
|
||||||
bool value;
|
bool value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GetThreadListRequest
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
union IPCSmsRequest
|
union IPCSmsRequest
|
||||||
{
|
{
|
||||||
SendMessageRequest;
|
SendMessageRequest;
|
||||||
|
@ -61,6 +65,7 @@ union IPCSmsRequest
|
||||||
CreateMessageListRequest;
|
CreateMessageListRequest;
|
||||||
GetNextMessageInListRequest;
|
GetNextMessageInListRequest;
|
||||||
MarkMessageReadRequest;
|
MarkMessageReadRequest;
|
||||||
|
GetThreadListRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
sync protocol PSms {
|
sync protocol PSms {
|
||||||
|
|
|
@ -85,6 +85,24 @@ struct ReplyNoMessageInList
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ThreadListItem
|
||||||
|
{
|
||||||
|
nsString senderOrReceiver;
|
||||||
|
uint64_t timestamp;
|
||||||
|
nsString body;
|
||||||
|
uint64_t unreadCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReplyThreadList
|
||||||
|
{
|
||||||
|
ThreadListItem[] items;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReplyThreadListFail
|
||||||
|
{
|
||||||
|
int32_t error;
|
||||||
|
};
|
||||||
|
|
||||||
union MessageReply
|
union MessageReply
|
||||||
{
|
{
|
||||||
ReplyMessageSend;
|
ReplyMessageSend;
|
||||||
|
@ -99,6 +117,8 @@ union MessageReply
|
||||||
ReplyGetNextMessage;
|
ReplyGetNextMessage;
|
||||||
ReplyMarkeMessageRead;
|
ReplyMarkeMessageRead;
|
||||||
ReplyMarkeMessageReadFail;
|
ReplyMarkeMessageReadFail;
|
||||||
|
ReplyThreadList;
|
||||||
|
ReplyThreadListFail;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sms
|
} // namespace sms
|
||||||
|
|
|
@ -161,6 +161,14 @@ SmsRequestChild::Recv__delete__(const MessageReply& aReply)
|
||||||
case MessageReply::TReplyMarkeMessageReadFail:
|
case MessageReply::TReplyMarkeMessageReadFail:
|
||||||
mReplyRequest->NotifyMarkMessageReadFailed(aReply.get_ReplyMarkeMessageReadFail().error());
|
mReplyRequest->NotifyMarkMessageReadFailed(aReply.get_ReplyMarkeMessageReadFail().error());
|
||||||
break;
|
break;
|
||||||
|
case MessageReply::TReplyThreadList: {
|
||||||
|
SmsRequestForwarder* forwarder = static_cast<SmsRequestForwarder*>(mReplyRequest.get());
|
||||||
|
SmsRequest* request = static_cast<SmsRequest*>(forwarder->GetRealRequest());
|
||||||
|
request->NotifyThreadList(aReply.get_ReplyThreadList().items());
|
||||||
|
} break;
|
||||||
|
case MessageReply::TReplyThreadListFail:
|
||||||
|
mReplyRequest->NotifyThreadListFailed(aReply.get_ReplyThreadListFail().error());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_NOT_REACHED("Received invalid response parameters!");
|
MOZ_NOT_REACHED("Received invalid response parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -179,6 +179,13 @@ SmsIPCService::MarkMessageRead(int32_t aMessageId,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SmsIPCService::GetThreadList(nsISmsRequest* aRequest)
|
||||||
|
{
|
||||||
|
SendRequest(GetThreadListRequest(), aRequest);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sms
|
} // namespace sms
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -203,6 +203,8 @@ SmsParent::RecvPSmsRequestConstructor(PSmsRequestParent* aActor,
|
||||||
return actor->DoRequest(aRequest.get_GetNextMessageInListRequest());
|
return actor->DoRequest(aRequest.get_GetNextMessageInListRequest());
|
||||||
case IPCSmsRequest::TMarkMessageReadRequest:
|
case IPCSmsRequest::TMarkMessageReadRequest:
|
||||||
return actor->DoRequest(aRequest.get_MarkMessageReadRequest());
|
return actor->DoRequest(aRequest.get_MarkMessageReadRequest());
|
||||||
|
case IPCSmsRequest::TGetThreadListRequest:
|
||||||
|
return actor->DoRequest(aRequest.get_GetThreadListRequest());
|
||||||
default:
|
default:
|
||||||
MOZ_NOT_REACHED("Unknown type!");
|
MOZ_NOT_REACHED("Unknown type!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -347,6 +349,21 @@ SmsRequestParent::DoRequest(const MarkMessageReadRequest& aRequest)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SmsRequestParent::DoRequest(const GetThreadListRequest& aRequest)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsISmsDatabaseService> smsDBService =
|
||||||
|
do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
|
||||||
|
|
||||||
|
NS_ENSURE_TRUE(smsDBService, true);
|
||||||
|
mSmsRequest = SmsRequest::Create(this);
|
||||||
|
nsCOMPtr<nsISmsRequest> forwarder = new SmsRequestForwarder(mSmsRequest);
|
||||||
|
nsresult rv = smsDBService->GetThreadList(forwarder);
|
||||||
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sms
|
} // namespace sms
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -103,6 +103,9 @@ protected:
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DoRequest(const MarkMessageReadRequest& aRequest);
|
DoRequest(const MarkMessageReadRequest& aRequest);
|
||||||
|
|
||||||
|
bool
|
||||||
|
DoRequest(const GetThreadListRequest& aRequest);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sms
|
} // namespace sms
|
||||||
|
|
|
@ -14,8 +14,9 @@ const RIL_SMSDATABASESERVICE_CID = Components.ID("{a1fa610c-eb6c-4ac2-878f-b005d
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
const DB_NAME = "sms";
|
const DB_NAME = "sms";
|
||||||
const DB_VERSION = 3;
|
const DB_VERSION = 4;
|
||||||
const STORE_NAME = "sms";
|
const STORE_NAME = "sms";
|
||||||
|
const MOST_RECENT_STORE_NAME = "most-recent";
|
||||||
|
|
||||||
const DELIVERY_SENT = "sent";
|
const DELIVERY_SENT = "sent";
|
||||||
const DELIVERY_RECEIVED = "received";
|
const DELIVERY_RECEIVED = "received";
|
||||||
|
@ -52,6 +53,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gIDBManager",
|
||||||
|
|
||||||
const GLOBAL_SCOPE = this;
|
const GLOBAL_SCOPE = this;
|
||||||
|
|
||||||
|
function numberFromMessage(message) {
|
||||||
|
return message.delivery == DELIVERY_SENT ? message.receiver : message.sender;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SmsDatabaseService
|
* SmsDatabaseService
|
||||||
*/
|
*/
|
||||||
|
@ -175,6 +180,10 @@ SmsDatabaseService.prototype = {
|
||||||
objectStore = event.target.transaction.objectStore(STORE_NAME);
|
objectStore = event.target.transaction.objectStore(STORE_NAME);
|
||||||
self.upgradeSchema2(objectStore);
|
self.upgradeSchema2(objectStore);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
if (DEBUG) debug("Upgrade to version 4. Add quick threads view.")
|
||||||
|
self.upgradeSchema3(event.target.transaction);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
event.target.transaction.abort();
|
event.target.transaction.abort();
|
||||||
callback("Old database version: " + event.oldVersion, null);
|
callback("Old database version: " + event.oldVersion, null);
|
||||||
|
@ -182,7 +191,7 @@ SmsDatabaseService.prototype = {
|
||||||
}
|
}
|
||||||
currentVersion++;
|
currentVersion++;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
request.onerror = function (event) {
|
request.onerror = function (event) {
|
||||||
//TODO look at event.target.Code and change error constant accordingly
|
//TODO look at event.target.Code and change error constant accordingly
|
||||||
callback("Error opening database!", null);
|
callback("Error opening database!", null);
|
||||||
|
@ -200,15 +209,22 @@ SmsDatabaseService.prototype = {
|
||||||
* @param callback
|
* @param callback
|
||||||
* Function to call when the transaction is available. It will
|
* Function to call when the transaction is available. It will
|
||||||
* be invoked with the transaction and the 'sms' object store.
|
* be invoked with the transaction and the 'sms' object store.
|
||||||
|
* @param objectStores
|
||||||
|
* Function to call when the transaction is available. It will
|
||||||
|
* be invoked with the transaction and the 'sms' object store.
|
||||||
*/
|
*/
|
||||||
newTxn: function newTxn(txn_type, callback) {
|
newTxn: function newTxn(txn_type, callback, objectStores) {
|
||||||
|
if (!objectStores) {
|
||||||
|
objectStores = [STORE_NAME];
|
||||||
|
}
|
||||||
|
if (DEBUG) debug("Opening transaction for objectStores: " + objectStores);
|
||||||
this.ensureDB(function (error, db) {
|
this.ensureDB(function (error, db) {
|
||||||
if (error) {
|
if (error) {
|
||||||
if (DEBUG) debug("Could not open database: " + error);
|
if (DEBUG) debug("Could not open database: " + error);
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let txn = db.transaction([STORE_NAME], txn_type);
|
let txn = db.transaction(objectStores, txn_type);
|
||||||
if (DEBUG) debug("Started transaction " + txn + " of type " + txn_type);
|
if (DEBUG) debug("Started transaction " + txn + " of type " + txn_type);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
txn.oncomplete = function oncomplete(event) {
|
txn.oncomplete = function oncomplete(event) {
|
||||||
|
@ -220,9 +236,18 @@ SmsDatabaseService.prototype = {
|
||||||
debug("Error occurred during transaction: " + event.target.errorCode);
|
debug("Error occurred during transaction: " + event.target.errorCode);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (DEBUG) debug("Retrieving object store", STORE_NAME);
|
let stores;
|
||||||
let store = txn.objectStore(STORE_NAME);
|
if (objectStores.length == 1) {
|
||||||
callback(null, txn, store);
|
if (DEBUG) debug("Retrieving object store " + objectStores[0]);
|
||||||
|
stores = txn.objectStore(objectStores[0]);
|
||||||
|
} else {
|
||||||
|
stores = [];
|
||||||
|
for each (let storeName in objectStores) {
|
||||||
|
if (DEBUG) debug("Retrieving object store " + storeName);
|
||||||
|
stores.push(txn.objectStore(storeName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(null, txn, stores);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -233,8 +258,8 @@ SmsDatabaseService.prototype = {
|
||||||
* TODO full text search on body???
|
* TODO full text search on body???
|
||||||
*/
|
*/
|
||||||
createSchema: function createSchema(db) {
|
createSchema: function createSchema(db) {
|
||||||
|
// This objectStore holds the main SMS data.
|
||||||
let objectStore = db.createObjectStore(STORE_NAME, { keyPath: "id" });
|
let objectStore = db.createObjectStore(STORE_NAME, { keyPath: "id" });
|
||||||
objectStore.createIndex("id", "id", { unique: true });
|
|
||||||
objectStore.createIndex("delivery", "delivery", { unique: false });
|
objectStore.createIndex("delivery", "delivery", { unique: false });
|
||||||
objectStore.createIndex("sender", "sender", { unique: false });
|
objectStore.createIndex("sender", "sender", { unique: false });
|
||||||
objectStore.createIndex("receiver", "receiver", { unique: false });
|
objectStore.createIndex("receiver", "receiver", { unique: false });
|
||||||
|
@ -246,7 +271,6 @@ SmsDatabaseService.prototype = {
|
||||||
* Upgrade to the corresponding database schema version.
|
* Upgrade to the corresponding database schema version.
|
||||||
*/
|
*/
|
||||||
upgradeSchema: function upgradeSchema(objectStore) {
|
upgradeSchema: function upgradeSchema(objectStore) {
|
||||||
// For now, the only possible upgrade is to version 2.
|
|
||||||
objectStore.createIndex("read", "read", { unique: false });
|
objectStore.createIndex("read", "read", { unique: false });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -265,6 +289,29 @@ SmsDatabaseService.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
upgradeSchema3: function upgradeSchema2(transaction) {
|
||||||
|
// Delete redundant "id" index.
|
||||||
|
let objectStore = transaction.objectStore(STORE_NAME);
|
||||||
|
if (objectStore.indexNames.contains("id")) {
|
||||||
|
objectStore.deleteIndex("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This objectStore can be used to quickly construct a thread view of the
|
||||||
|
* SMS database. Each entry looks like this:
|
||||||
|
*
|
||||||
|
* { senderOrReceiver: <String> (primary key),
|
||||||
|
* id: <Number>,
|
||||||
|
* timestamp: <Date>,
|
||||||
|
* body: <String>,
|
||||||
|
* unreadCount: <Number> }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
objectStore = db.createObjectStore(MOST_RECENT_STORE_NAME,
|
||||||
|
{ keyPath: "senderOrReceiver" });
|
||||||
|
objectStore.createIndex("timestamp", "timestamp");
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to make the intersection of the partial result arrays
|
* Helper function to make the intersection of the partial result arrays
|
||||||
* obtained within createMessageList.
|
* obtained within createMessageList.
|
||||||
|
@ -354,12 +401,43 @@ SmsDatabaseService.prototype = {
|
||||||
this.lastKey += 1;
|
this.lastKey += 1;
|
||||||
message.id = this.lastKey;
|
message.id = this.lastKey;
|
||||||
if (DEBUG) debug("Going to store " + JSON.stringify(message));
|
if (DEBUG) debug("Going to store " + JSON.stringify(message));
|
||||||
this.newTxn(READ_WRITE, function(error, txn, store) {
|
this.newTxn(READ_WRITE, function(error, txn, stores) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let request = store.put(message);
|
// First add to main objectStore.
|
||||||
});
|
stores[0].put(message);
|
||||||
|
|
||||||
|
let number = numberFromMessage(message);
|
||||||
|
|
||||||
|
// Next update the other objectStore.
|
||||||
|
stores[1].get(number).onsuccess = function(event) {
|
||||||
|
let mostRecentEntry = event.target.result;
|
||||||
|
if (mostRecentEntry) {
|
||||||
|
let needsUpdate = false;
|
||||||
|
|
||||||
|
if (mostRecentEntry.timestamp <= message.timestamp) {
|
||||||
|
mostRecentEntry.timestamp = message.timestamp;
|
||||||
|
mostRecentEntry.body = message.body;
|
||||||
|
needsUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!message.read) {
|
||||||
|
mostRecentEntry.unreadCount++;
|
||||||
|
needsUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsUpdate) {
|
||||||
|
event.target.source.put(mostRecentEntry);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event.target.source.add({ senderOrReceiver: number,
|
||||||
|
timestamp: message.timestamp,
|
||||||
|
body: message.body,
|
||||||
|
unreadCount: message.read ? 0 : 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [STORE_NAME, MOST_RECENT_STORE_NAME]);
|
||||||
// We return the key that we expect to store in the db
|
// We return the key that we expect to store in the db
|
||||||
return message.id;
|
return message.id;
|
||||||
},
|
},
|
||||||
|
@ -499,33 +577,103 @@ SmsDatabaseService.prototype = {
|
||||||
deleteMessage: function deleteMessage(messageId, aRequest) {
|
deleteMessage: function deleteMessage(messageId, aRequest) {
|
||||||
let deleted = false;
|
let deleted = false;
|
||||||
let self = this;
|
let self = this;
|
||||||
this.newTxn(READ_WRITE, function (error, txn, store) {
|
this.newTxn(READ_WRITE, function (error, txn, stores) {
|
||||||
if (error) {
|
if (error) {
|
||||||
aRequest.notifyDeleteMessageFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
aRequest.notifyDeleteMessageFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let request = store.count(messageId);
|
txn.onerror = function onerror(event) {
|
||||||
|
if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
|
||||||
request.onsuccess = function onsuccess(event) {
|
//TODO look at event.target.errorCode, pick appropriate error constant
|
||||||
let count = event.target.result;
|
aRequest.notifyDeleteMessageFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
||||||
if (DEBUG) debug("Count for messageId " + messageId + ": " + count);
|
|
||||||
deleted = (count == 1);
|
|
||||||
if (deleted) {
|
|
||||||
store.delete(messageId);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const smsStore = stores[0];
|
||||||
|
const mruStore = stores[1];
|
||||||
|
|
||||||
|
let deleted = false;
|
||||||
|
|
||||||
txn.oncomplete = function oncomplete(event) {
|
txn.oncomplete = function oncomplete(event) {
|
||||||
if (DEBUG) debug("Transaction " + txn + " completed.");
|
if (DEBUG) debug("Transaction " + txn + " completed.");
|
||||||
aRequest.notifyMessageDeleted(deleted);
|
aRequest.notifyMessageDeleted(deleted);
|
||||||
};
|
};
|
||||||
|
|
||||||
txn.onerror = function onerror(event) {
|
smsStore.get(messageId).onsuccess = function(event) {
|
||||||
if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
|
let message = event.target.result;
|
||||||
//TODO look at event.target.errorCode, pick appropriate error constant
|
if (message) {
|
||||||
aRequest.notifyDeleteMessageFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
if (DEBUG) debug("Deleting message id " + messageId);
|
||||||
|
|
||||||
|
// First actually delete the message.
|
||||||
|
event.target.source.delete(messageId).onsuccess = function(event) {
|
||||||
|
deleted = true;
|
||||||
|
|
||||||
|
// Then update unread count and most recent message.
|
||||||
|
let number = numberFromMessage(message);
|
||||||
|
|
||||||
|
mruStore.get(number).onsuccess = function(event) {
|
||||||
|
// This must exist.
|
||||||
|
let mostRecentEntry = event.target.result;
|
||||||
|
|
||||||
|
if (!message.read) {
|
||||||
|
mostRecentEntry.unreadCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mostRecentEntry.id == messageId) {
|
||||||
|
// This sucks, we have to find a new most-recent message.
|
||||||
|
message = null;
|
||||||
|
|
||||||
|
// Check most recent sender.
|
||||||
|
smsStore.index("sender").openCursor(number, "prev").onsuccess = function(event) {
|
||||||
|
let cursor = event.target.result;
|
||||||
|
if (cursor) {
|
||||||
|
message = cursor.value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
// Check most recent receiver.
|
||||||
|
smsStore.index("receiver").openCursor(number, "prev").onsuccess = function(event) {
|
||||||
|
let cursor = event.target.result;
|
||||||
|
if (cursor) {
|
||||||
|
if (!message || cursor.value.timeStamp > message.timestamp) {
|
||||||
|
message = cursor.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found a new message then we need to update the data
|
||||||
|
// in the most-recent store. Otherwise we can delete it.
|
||||||
|
if (message) {
|
||||||
|
mostRecentEntry.id = message.id;
|
||||||
|
mostRecentEntry.timestamp = message.timestamp;
|
||||||
|
mostRecentEntry.body = message.body;
|
||||||
|
if (DEBUG) {
|
||||||
|
debug("Updating mru entry: " +
|
||||||
|
JSON.stringify(mostRecentEntry));
|
||||||
|
}
|
||||||
|
mruStore.put(mostRecentEntry);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (DEBUG) {
|
||||||
|
debug("Deleting mru entry for number '" + number + "'");
|
||||||
|
}
|
||||||
|
mruStore.delete(number);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else if (!message.read) {
|
||||||
|
// Shortcut, just update the unread count.
|
||||||
|
if (DEBUG) {
|
||||||
|
debug("Updating unread count for number '" + number + "': " +
|
||||||
|
(mostRecentEntry.unreadCount + 1) + " -> " +
|
||||||
|
mostRecentEntry.unreadCount);
|
||||||
|
}
|
||||||
|
mruStore.put(mostRecentEntry);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else if (DEBUG) {
|
||||||
|
debug("Message id " + messageId + " does not exist");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [STORE_NAME, MOST_RECENT_STORE_NAME]);
|
||||||
},
|
},
|
||||||
|
|
||||||
createMessageList: function createMessageList(filter, reverse, aRequest) {
|
createMessageList: function createMessageList(filter, reverse, aRequest) {
|
||||||
|
@ -726,18 +874,20 @@ SmsDatabaseService.prototype = {
|
||||||
|
|
||||||
markMessageRead: function markMessageRead(messageId, value, aRequest) {
|
markMessageRead: function markMessageRead(messageId, value, aRequest) {
|
||||||
if (DEBUG) debug("Setting message " + messageId + " read to " + value);
|
if (DEBUG) debug("Setting message " + messageId + " read to " + value);
|
||||||
this.newTxn(READ_WRITE, function (error, txn, store) {
|
this.newTxn(READ_WRITE, function (error, txn, stores) {
|
||||||
if (error) {
|
if (error) {
|
||||||
if (DEBUG) debug(error);
|
if (DEBUG) debug(error);
|
||||||
aRequest.notifyMarkMessageReadFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
aRequest.notifyMarkMessageReadFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let getRequest = store.get(messageId);
|
txn.onerror = function onerror(event) {
|
||||||
|
if (DEBUG) debug("Caught error on transaction ", event.target.errorCode);
|
||||||
getRequest.onsuccess = function onsuccess(event) {
|
aRequest.notifyMarkMessageReadFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
||||||
|
};
|
||||||
|
stores[0].get(messageId).onsuccess = function onsuccess(event) {
|
||||||
let message = event.target.result;
|
let message = event.target.result;
|
||||||
if (DEBUG) debug("Message ID " + messageId + " not found");
|
|
||||||
if (!message) {
|
if (!message) {
|
||||||
|
if (DEBUG) debug("Message ID " + messageId + " not found");
|
||||||
aRequest.notifyMarkMessageReadFailed(Ci.nsISmsRequest.NOT_FOUND_ERROR);
|
aRequest.notifyMarkMessageReadFailed(Ci.nsISmsRequest.NOT_FOUND_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -758,26 +908,50 @@ SmsDatabaseService.prototype = {
|
||||||
}
|
}
|
||||||
message.read = value ? FILTER_READ_READ : FILTER_READ_UNREAD;
|
message.read = value ? FILTER_READ_READ : FILTER_READ_UNREAD;
|
||||||
if (DEBUG) debug("Message.read set to: " + value);
|
if (DEBUG) debug("Message.read set to: " + value);
|
||||||
let putRequest = store.put(message);
|
event.target.source.put(message).onsuccess = function onsuccess(event) {
|
||||||
putRequest.onsuccess = function onsuccess(event) {
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
debug("Update successfully completed. Message: " +
|
debug("Update successfully completed. Message: " +
|
||||||
JSON.stringify(event.target.result));
|
JSON.stringify(event.target.result));
|
||||||
}
|
}
|
||||||
let checkRequest = store.get(message.id);
|
|
||||||
checkRequest.onsuccess = function onsuccess(event) {
|
|
||||||
aRequest.notifyMessageMarkedRead(event.target.result.read);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Now update the unread count.
|
||||||
|
let number = numberFromMessage(message);
|
||||||
|
|
||||||
|
stores[1].get(number).onsuccess = function(event) {
|
||||||
|
let mostRecentEntry = event.target.result;
|
||||||
|
mostRecentEntry.unreadCount += value ? -1 : 1;
|
||||||
|
if (DEBUG) {
|
||||||
|
debug("Updating unreadCount for '" + number + "': " +
|
||||||
|
(value ?
|
||||||
|
mostRecentEntry.unreadCount + 1 :
|
||||||
|
mostRecentEntry.unreadCount - 1) +
|
||||||
|
" -> " + mostRecentEntry.unreadCount);
|
||||||
|
}
|
||||||
|
event.target.source.put(mostRecentEntry).onsuccess = function(event) {
|
||||||
|
aRequest.notifyMessageMarkedRead(message.read);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}, [STORE_NAME, MOST_RECENT_STORE_NAME]);
|
||||||
|
},
|
||||||
|
getThreadList: function getThreadList(aRequest) {
|
||||||
|
if (DEBUG) debug("Getting thread list");
|
||||||
|
this.newTxn(READ_ONLY, function (error, txn, store) {
|
||||||
|
if (error) {
|
||||||
|
if (DEBUG) debug(error);
|
||||||
|
aRequest.notifyThreadListFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
txn.onerror = function onerror(event) {
|
txn.onerror = function onerror(event) {
|
||||||
if (DEBUG) debug("Caught error on transaction ", event.target.errorCode);
|
if (DEBUG) debug("Caught error on transaction ", event.target.errorCode);
|
||||||
aRequest.notifyMarkMessageReadFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
aRequest.notifyThreadListFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
|
||||||
};
|
};
|
||||||
});
|
store.index("timestamp").mozGetAll().onsuccess = function(event) {
|
||||||
|
aRequest.notifyThreadList(event.target.result);
|
||||||
|
};
|
||||||
|
}, [MOST_RECENT_STORE_NAME]);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(SmsDatabaseService.prototype, "mRIL", function () {
|
XPCOMUtils.defineLazyGetter(SmsDatabaseService.prototype, "mRIL", function () {
|
||||||
|
|
|
@ -22,7 +22,8 @@ dictionaries = [
|
||||||
[ 'CameraPosition', 'nsIDOMCameraManager.idl' ],
|
[ 'CameraPosition', 'nsIDOMCameraManager.idl' ],
|
||||||
[ 'CameraSelector', 'nsIDOMCameraManager.idl' ],
|
[ 'CameraSelector', 'nsIDOMCameraManager.idl' ],
|
||||||
[ 'CameraPictureOptions', 'nsIDOMCameraManager.idl' ],
|
[ 'CameraPictureOptions', 'nsIDOMCameraManager.idl' ],
|
||||||
[ 'CameraRecordingOptions', 'nsIDOMCameraManager.idl' ]
|
[ 'CameraRecordingOptions', 'nsIDOMCameraManager.idl' ],
|
||||||
|
[ 'SmsThreadListItem', 'nsISmsRequest.idl' ]
|
||||||
]
|
]
|
||||||
|
|
||||||
# include file names
|
# include file names
|
||||||
|
|
Загрузка…
Ссылка в новой задаче