2014-08-29 01:04:17 +04:00
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set shiftwidth=4 tabstop=4 autoindent cindent expandtab: */
2014-08-29 01:13:45 +04:00
'use strict' ;
2014-08-29 01:04:17 +04:00
var LocalMsgConnection = function ( ) {
this . waitingForConnection = null ;
2014-11-27 11:36:10 +03:00
this . serverWaiting = [ ] ;
this . clientWaiting = [ ] ;
2014-08-29 01:04:17 +04:00
this . serverMessages = [ ] ;
this . clientMessages = [ ] ;
}
LocalMsgConnection . prototype . notifyConnection = function ( ) {
if ( this . waitingForConnection ) {
this . waitingForConnection ( ) ;
}
}
2014-10-17 02:04:31 +04:00
LocalMsgConnection . prototype . waitConnection = function ( ) {
return new Promise ( ( function ( resolve , reject ) {
this . waitingForConnection = function ( ) {
this . waitingForConnection = null ;
resolve ( ) ;
}
} ) . bind ( this ) ) ;
2014-08-29 01:04:17 +04:00
}
LocalMsgConnection . prototype . copyMessage = function ( messageQueue , data ) {
var msg = messageQueue . shift ( ) ;
for ( var i = 0 ; i < msg . length ; i ++ ) {
data [ i ] = msg . data [ i + msg . offset ] ;
}
2014-09-08 20:27:41 +04:00
return msg . length ;
2014-08-29 01:04:17 +04:00
}
LocalMsgConnection . prototype . sendMessageToClient = function ( message ) {
this . clientMessages . push ( message ) ;
2014-11-27 11:36:10 +03:00
if ( this . clientWaiting . length > 0 ) {
this . clientWaiting . shift ( ) ( ) ;
2014-08-29 01:04:17 +04:00
}
}
2014-10-17 02:04:31 +04:00
LocalMsgConnection . prototype . clientReceiveMessage = function ( data ) {
return new Promise ( ( function ( resolve , reject ) {
if ( this . clientMessages . length == 0 ) {
2014-11-27 11:36:10 +03:00
this . clientWaiting . push ( function ( ) {
2014-10-17 02:04:31 +04:00
resolve ( this . copyMessage ( this . clientMessages , data ) ) ;
2014-11-27 11:36:10 +03:00
} . bind ( this ) ) ;
2014-08-29 01:04:17 +04:00
2014-10-17 02:04:31 +04:00
return ;
2014-08-29 01:04:17 +04:00
}
2014-10-17 02:04:31 +04:00
resolve ( this . copyMessage ( this . clientMessages , data ) ) ;
} ) . bind ( this ) ) ;
2014-08-29 01:04:17 +04:00
}
LocalMsgConnection . prototype . sendMessageToServer = function ( message ) {
this . serverMessages . push ( message ) ;
2014-11-27 11:36:10 +03:00
if ( this . serverWaiting . length > 0 ) {
this . serverWaiting . shift ( ) ( ) ;
2014-08-29 01:04:17 +04:00
}
}
2014-10-17 02:04:31 +04:00
LocalMsgConnection . prototype . serverReceiveMessage = function ( data ) {
return new Promise ( ( function ( resolve , reject ) {
if ( this . serverMessages . length == 0 ) {
2014-11-27 11:36:10 +03:00
this . serverWaiting . push ( function ( ) {
2014-10-17 02:04:31 +04:00
resolve ( this . copyMessage ( this . serverMessages , data ) ) ;
2014-11-27 11:36:10 +03:00
} . bind ( this ) ) ;
2014-10-17 02:04:31 +04:00
return ;
2014-08-29 01:04:17 +04:00
}
2014-10-17 02:04:31 +04:00
resolve ( this . copyMessage ( this . serverMessages , data ) ) ;
} ) . bind ( this ) ) ;
2014-08-29 01:04:17 +04:00
}
2014-09-10 05:44:46 +04:00
var NokiaMessagingLocalMsgConnection = function ( ) {
2014-09-10 03:07:40 +04:00
LocalMsgConnection . call ( this ) ;
2014-11-27 11:36:10 +03:00
window . addEventListener ( "nokia.messaging" , function ( e ) {
this . receiveSMS ( e . detail ) ;
} . bind ( this ) ) ;
2014-09-10 03:07:40 +04:00
}
2014-09-10 05:44:46 +04:00
NokiaMessagingLocalMsgConnection . prototype = Object . create ( LocalMsgConnection . prototype ) ;
NokiaMessagingLocalMsgConnection . prototype . receiveSMS = function ( sms ) {
var encoder = new DataEncoder ( ) ;
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "MessageNotify" ) ;
2014-09-10 21:47:56 +04:00
encoder . put ( DataType . USHORT , "trans_id" , Date . now ( ) % 255 ) ; // The meaning of this field is unknown
2014-09-10 05:44:46 +04:00
encoder . put ( DataType . STRING , "type" , "SMS" ) ; // The name of this field is unknown
2014-09-10 21:42:51 +04:00
encoder . put ( DataType . ULONG , "message_id" , sms . id ) ;
2014-09-10 05:44:46 +04:00
encoder . putEnd ( DataType . STRUCT , "event" ) ;
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
}
NokiaMessagingLocalMsgConnection . prototype . sendMessageToServer = function ( message ) {
var encoder = new DataEncoder ( ) ;
2014-09-10 03:07:40 +04:00
var decoder = new DataDecoder ( message . data , message . offset , message . length ) ;
2014-09-10 05:44:46 +04:00
decoder . getStart ( DataType . STRUCT ) ;
var name = decoder . getValue ( DataType . METHOD ) ;
2014-09-10 21:49:51 +04:00
2014-09-10 05:44:46 +04:00
switch ( name ) {
case "Common" :
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Common" ) ;
encoder . putStart ( DataType . STRUCT , "message" ) ;
encoder . put ( DataType . METHOD , "name" , "ProtocolVersion" ) ;
encoder . put ( DataType . STRING , "version" , "2.[0-10]" ) ;
encoder . putEnd ( DataType . STRUCT , "message" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
break ;
case "SubscribeMessages" :
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "SubscribeMessages" ) ;
2014-09-10 21:06:00 +04:00
encoder . put ( DataType . USHORT , "trans_id" , decoder . getValue ( DataType . USHORT ) ) ; // The meaning of this field is unknown
2014-09-10 05:44:46 +04:00
encoder . put ( DataType . STRING , "result" , "OK" ) ; // The name of this field is unknown
encoder . putEnd ( DataType . STRUCT , "event" ) ;
break ;
case "GetMessageEntity" :
2014-09-10 21:06:00 +04:00
var trans _id = decoder . getValue ( DataType . USHORT ) ;
2014-09-10 05:44:46 +04:00
var sms _id = decoder . getValue ( DataType . ULONG ) ;
var sms ;
2014-09-11 01:01:31 +04:00
for ( var i = 0 ; i < MIDP . nokiaSMSMessages . length ; i ++ ) {
if ( MIDP . nokiaSMSMessages [ i ] . id == sms _id ) {
sms = MIDP . nokiaSMSMessages [ i ] ;
break ;
2014-09-10 05:44:46 +04:00
}
}
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "GetMessageEntity" ) ;
2014-09-10 21:06:00 +04:00
encoder . put ( DataType . USHORT , "trans_id" , trans _id ) ; // The meaning of this field is unknown
2014-09-10 05:44:46 +04:00
encoder . put ( DataType . STRING , "result" , "OK" ) ; // The name of this field is unknown
encoder . put ( DataType . ULONG , "message_id" , sms _id ) ;
encoder . putStart ( DataType . LIST , "list_name_unknown" ) ; // The name of this field is unknown
encoder . put ( DataType . WSTRING , "body_text" , sms . text ) ;
encoder . put ( DataType . STRING , "address" , sms . addr ) ;
encoder . putEnd ( DataType . LIST ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
break ;
case "DeleteMessages" :
decoder . getValue ( DataType . USHORT ) ;
decoder . getStart ( DataType . ARRAY ) ;
var sms _id = decoder . getValue ( DataType . ULONG ) ;
2014-09-10 21:14:56 +04:00
2014-09-11 01:01:31 +04:00
for ( var i = 0 ; i < MIDP . nokiaSMSMessages . length ; i ++ ) {
if ( MIDP . nokiaSMSMessages [ i ] . id == sms _id ) {
MIDP . nokiaSMSMessages . splice ( i , 1 ) ;
break ;
2014-09-10 21:14:56 +04:00
}
}
2014-11-01 15:53:36 +03:00
return ;
2014-09-10 05:44:46 +04:00
break ;
default :
2014-09-19 22:35:12 +04:00
console . error ( "(nokia.messaging) event " + name + " not implemented " +
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
2014-09-10 05:44:46 +04:00
return ;
}
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
2014-09-10 03:07:40 +04:00
}
2014-11-21 13:05:04 +03:00
var NokiaSASrvRegLocalMsgConnection = function ( ) {
LocalMsgConnection . call ( this ) ;
} ;
NokiaSASrvRegLocalMsgConnection . prototype = Object . create ( LocalMsgConnection . prototype ) ;
NokiaSASrvRegLocalMsgConnection . prototype . sendMessageToServer = function ( message ) {
var decoder = new DataDecoder ( message . data , message . offset , message . length ) ;
decoder . getStart ( DataType . STRUCT ) ;
var name = decoder . getValue ( DataType . METHOD ) ;
var encoder = new DataEncoder ( ) ;
switch ( name ) {
case "Common" :
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Common" ) ;
encoder . putStart ( DataType . STRUCT , "message" ) ;
encoder . put ( DataType . METHOD , "name" , "ProtocolVersion" ) ;
encoder . put ( DataType . STRING , "version" , "2.0" ) ;
encoder . putEnd ( DataType . STRUCT , "message" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
break ;
case "Discovery" :
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Discovery" ) ;
encoder . put ( DataType . BYTE , "unknown_byte_1" , 1 ) ;
encoder . put ( DataType . STRING , "unknown_string_1" , "" ) ;
encoder . putStart ( DataType . ARRAY , "services" ) ;
encoder . putStart ( DataType . STRUCT , "service" ) ;
encoder . put ( DataType . STRING , "ServiceName" , "file_ui" ) ;
encoder . put ( DataType . URI , "ServiceURI" , "nokia.file-ui" ) ;
encoder . put ( DataType . STRING , "unknown_string_2" , "" ) ;
encoder . put ( DataType . WSTRING , "unknown_string_3" , "" ) ;
encoder . put ( DataType . STRING , "unknown_string_4" , "" ) ;
encoder . putEnd ( DataType . STRUCT , "service" ) ;
encoder . putEnd ( DataType . ARRAY , "services" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
break ;
}
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
} ;
2014-10-14 13:18:38 +04:00
var NokiaPhoneStatusLocalMsgConnection = function ( ) {
LocalMsgConnection . call ( this ) ;
} ;
NokiaPhoneStatusLocalMsgConnection . prototype = Object . create ( LocalMsgConnection . prototype ) ;
NokiaPhoneStatusLocalMsgConnection . prototype . sendMessageToServer = function ( message ) {
var decoder = new DataDecoder ( message . data , message . offset , message . length ) ;
decoder . getStart ( DataType . STRUCT ) ;
var name = decoder . getValue ( DataType . METHOD ) ;
var encoder = new DataEncoder ( ) ;
switch ( name ) {
case "Common" :
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Common" ) ;
encoder . putStart ( DataType . STRUCT , "message" ) ;
encoder . put ( DataType . METHOD , "name" , "ProtocolVersion" ) ;
encoder . put ( DataType . STRING , "version" , "2.[0-10]" ) ;
encoder . putEnd ( DataType . STRUCT , "message" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
break ;
case "Query" :
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Query" ) ;
encoder . put ( DataType . STRING , "status" , "OK" ) ;
encoder . putStart ( DataType . LIST , "subscriptions" ) ;
// subscriptions
decoder . getStart ( DataType . LIST ) ;
while ( decoder . getTag ( ) == DataType . STRING ) {
switch ( decoder . getName ( ) ) {
case "network_status" :
encoder . putStart ( DataType . STRUCT , "network_status" ) ;
encoder . put ( DataType . STRING , "" , "" ) ; // unknow name
encoder . put ( DataType . BOOLEAN , "" , 1 ) ; // unknow name
encoder . putEnd ( DataType . STRUCT , "network_status" ) ;
break ;
case "wifi_status" :
encoder . putStart ( DataType . STRUCT , "wifi_status" ) ;
encoder . put ( DataType . BOOLEAN , "" , 1 ) ; // unknow name, but it should indicate if the wifi is connected, and let's assume it's always connected.
encoder . putEnd ( DataType . STRUCT , "wifi_status" ) ;
break ;
case "battery" :
encoder . putStart ( DataType . STRUCT , "battery" ) ;
encoder . put ( DataType . BYTE , "" , 1 ) ; // unknow name
encoder . put ( DataType . BOOLEAN , "" , 1 ) ; // unknow name
encoder . putEnd ( DataType . STRUCT , "battery" ) ;
break ;
default :
console . error ( "(nokia.phone-status) Query " + decoder . getName ( ) + " not implemented " +
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
break ;
}
decoder . getValue ( DataType . STRING ) ;
}
encoder . putEnd ( DataType . LIST , "subscriptions" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
break ;
default :
console . error ( "(nokia.phone-status) event " + name + " not implemented " +
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
return ;
}
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
} ;
2014-10-31 13:30:09 +03:00
var NokiaContactsLocalMsgConnection = function ( ) {
LocalMsgConnection . call ( this ) ;
}
2014-09-17 02:33:11 +04:00
NokiaContactsLocalMsgConnection . prototype = Object . create ( LocalMsgConnection . prototype ) ;
2014-11-06 21:06:57 +03:00
NokiaContactsLocalMsgConnection . prototype . encodeContact = function ( encoder , contact ) {
2014-09-19 22:30:35 +04:00
encoder . putStart ( DataType . LIST , "Contact" ) ;
2014-11-07 04:06:37 +03:00
encoder . put ( DataType . WSTRING , "ContactID" , contact . id . toString ( ) . substr ( 0 , 30 ) ) ;
2014-09-19 22:30:35 +04:00
encoder . put ( DataType . WSTRING , "DisplayName" , contact . name [ 0 ] ) ;
2014-11-20 03:49:01 +03:00
encoder . putStart ( DataType . ARRAY , "Numbers" ) ;
contact . tel . forEach ( function ( tel ) {
encoder . putStart ( DataType . LIST , "NumbersList" ) ; // The name of this field is unknown
// encoder.put(DataType.ULONG, "Kind", ???); // The meaning of this field is unknown
encoder . put ( DataType . WSTRING , "Number" , tel . value ) ;
encoder . putEnd ( DataType . LIST , "NumbersList" ) ;
} ) ;
encoder . putEnd ( DataType . ARRAY , "Numbers" ) ;
2014-09-19 22:30:35 +04:00
encoder . putEnd ( DataType . LIST , "Contact" ) ;
2014-11-06 21:06:57 +03:00
}
NokiaContactsLocalMsgConnection . prototype . sendContact = function ( trans _id , contact ) {
2014-11-20 03:49:01 +03:00
if ( ! contact . tel ) {
return ;
}
2014-11-06 21:06:57 +03:00
var encoder = new DataEncoder ( ) ;
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Notify" ) ;
encoder . put ( DataType . ULONG , "trans_id" , trans _id ) ; // The meaning of this field is unknown
encoder . put ( DataType . BYTE , "type" , 1 ) ; // The name of this field is unknown (the value may be 1, 2, 3 according to the event (I'd guess CREATE, DELETE, UPDATE))
this . encodeContact ( encoder , contact ) ;
2014-09-19 22:30:35 +04:00
encoder . putEnd ( DataType . STRUCT , "event" ) ;
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
} ;
2014-09-17 02:33:11 +04:00
2014-09-19 22:30:35 +04:00
NokiaContactsLocalMsgConnection . prototype . sendMessageToServer = function ( message ) {
2014-09-17 02:33:11 +04:00
var decoder = new DataDecoder ( message . data , message . offset , message . length ) ;
decoder . getStart ( DataType . STRUCT ) ;
var name = decoder . getValue ( DataType . METHOD ) ;
switch ( name ) {
case "Common" :
2014-09-19 22:30:35 +04:00
var encoder = new DataEncoder ( ) ;
2014-09-17 02:33:11 +04:00
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Common" ) ;
encoder . putStart ( DataType . STRUCT , "message" ) ;
encoder . put ( DataType . METHOD , "name" , "ProtocolVersion" ) ;
encoder . put ( DataType . STRING , "version" , "2.[0-10]" ) ;
encoder . putEnd ( DataType . STRUCT , "message" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
2014-09-19 22:30:35 +04:00
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
2014-09-17 02:33:11 +04:00
break ;
case "NotifySubscribe" :
2014-09-19 22:30:35 +04:00
contacts . forEach ( this . sendContact . bind ( this , decoder . getValue ( DataType . ULONG ) ) ) ;
2014-09-17 02:33:11 +04:00
break ;
2014-11-06 11:29:25 +03:00
case "getFirst" :
var trans _id = decoder . getValue ( DataType . ULONG ) ;
decoder . getEnd ( DataType . ARRAY ) ; // Ignore the contents of the "sources" array
var numEntries = decoder . getValue ( DataType . ULONG ) ;
if ( numEntries !== 1 ) {
console . error ( "(nokia.contacts) event getFirst with numEntries != 1 not implemented " +
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
}
2014-11-06 21:06:57 +03:00
2014-11-20 04:01:05 +03:00
var gotContact = ( function ( contact ) {
2014-11-20 04:07:20 +03:00
if ( contact && ! contact . tel ) {
2014-11-20 03:56:55 +03:00
contacts . getNext ( gotContact ) ;
return ;
}
2014-11-06 21:06:57 +03:00
var encoder = new DataEncoder ( ) ;
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "getFirst" ) ;
encoder . put ( DataType . ULONG , "trans_id" , trans _id ) ;
2014-11-20 03:56:55 +03:00
if ( contact ) {
2014-11-06 21:06:57 +03:00
encoder . put ( DataType . STRING , "result" , "OK" ) ; // Name unknown
encoder . putStart ( DataType . ARRAY , "contacts" ) ; // Name unknown
this . encodeContact ( encoder , contact ) ;
encoder . putEnd ( DataType . ARRAY , "contacts" ) ; // Name unknown
} else {
encoder . put ( DataType . STRING , "result" , "Entry not found" ) ; // Name unknown
}
encoder . putEnd ( DataType . STRUCT , "event" ) ;
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
2014-11-20 03:56:55 +03:00
} ) . bind ( this ) ;
contacts . getNext ( gotContact ) ;
2014-11-06 11:29:25 +03:00
break ;
case "getNext" :
var trans _id = decoder . getValue ( DataType . ULONG ) ;
decoder . getEnd ( DataType . ARRAY ) ; // Ignore the contents of the "sources" array
decoder . getEnd ( DataType . LIST ) ; // Ignore the contents of the "filter" list
decoder . getStart ( DataType . LIST ) ;
var contactID = decoder . getValue ( DataType . WSTRING ) ;
decoder . getEnd ( DataType . LIST ) ;
var includeStartEntry = decoder . getValue ( DataType . BOOLEAN ) ;
if ( includeStartEntry == 1 ) {
console . error ( "(nokia.contacts) event getNext with includeStartEntry == true not implemented " +
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
}
var numEntries = decoder . getValue ( DataType . ULONG ) ;
if ( numEntries !== 1 ) {
console . error ( "(nokia.contacts) event getNext with numEntries != 1 not implemented " +
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
}
2014-11-06 21:06:57 +03:00
contacts . getNext ( ( function ( contact ) {
var encoder = new DataEncoder ( ) ;
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "getNext" ) ;
encoder . put ( DataType . ULONG , "trans_id" , trans _id ) ;
if ( contact ) {
encoder . put ( DataType . STRING , "result" , "OK" ) ; // Name unknown
encoder . putStart ( DataType . ARRAY , "contacts" ) ; // Name unknown
this . encodeContact ( encoder , contact ) ;
encoder . putEnd ( DataType . ARRAY , "contacts" ) ; // Name unknown
} else {
encoder . put ( DataType . STRING , "result" , "Entry not found" ) ; // Name unknown
}
encoder . putEnd ( DataType . STRUCT , "event" ) ;
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
} ) . bind ( this ) ) ;
2014-11-06 11:29:25 +03:00
break ;
2014-09-17 02:33:11 +04:00
default :
2014-09-19 22:35:12 +04:00
console . error ( "(nokia.contacts) event " + name + " not implemented " +
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
2014-09-17 02:33:11 +04:00
return ;
}
}
2014-10-31 13:30:09 +03:00
var NokiaFileUILocalMsgConnection = function ( ) {
LocalMsgConnection . call ( this ) ;
} ;
NokiaFileUILocalMsgConnection . prototype = Object . create ( LocalMsgConnection . prototype ) ;
NokiaFileUILocalMsgConnection . prototype . sendMessageToServer = function ( message ) {
var decoder = new DataDecoder ( message . data , message . offset , message . length ) ;
decoder . getStart ( DataType . STRUCT ) ;
var name = decoder . getValue ( DataType . METHOD ) ;
switch ( name ) {
case "Common" :
2014-11-01 15:52:31 +03:00
var encoder = new DataEncoder ( ) ;
2014-10-31 13:30:09 +03:00
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Common" ) ;
encoder . putStart ( DataType . STRUCT , "message" ) ;
encoder . put ( DataType . METHOD , "name" , "ProtocolVersion" ) ;
encoder . put ( DataType . STRING , "version" , "1.0" ) ;
encoder . putEnd ( DataType . STRUCT , "message" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
2014-11-01 15:52:31 +03:00
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
2014-10-31 13:30:09 +03:00
break ;
case "FileSelect" :
var trans _id = decoder . getValue ( DataType . USHORT ) ;
var storageType = decoder . getValue ( DataType . STRING ) ;
var mediaType = decoder . getValue ( DataType . STRING ) ;
var multipleSelection = decoder . getValue ( DataType . BOOLEAN ) ;
var startingURL = decoder . getValue ( DataType . STRING ) ;
2014-11-19 01:01:41 +03:00
var accept = '' ;
switch ( mediaType ) {
case "Picture" :
accept = "image/*" ;
break ;
case "Video" :
accept = "video/*" ;
break ;
case "Music" :
accept = "audio/*" ;
break ;
default :
throw new Error ( "Media type '" + mediaType + "' not supported" ) ;
}
2014-11-01 15:52:31 +03:00
var el = document . getElementById ( 'nokia-fileui-prompt' ) . cloneNode ( true ) ;
el . style . display = 'block' ;
el . classList . add ( 'visible' ) ;
2014-11-19 01:01:41 +03:00
var fileInput = el . querySelector ( 'input' ) ;
fileInput . accept = accept ;
2014-11-02 22:04:24 +03:00
var btnDone = el . querySelector ( 'button.recommend' ) ;
btnDone . disabled = true ;
2014-11-01 15:52:31 +03:00
var selectedFile = null ;
2014-11-19 01:01:41 +03:00
fileInput . addEventListener ( 'change' , function ( ) {
2014-11-02 22:04:24 +03:00
btnDone . disabled = false ;
2014-11-01 15:52:31 +03:00
selectedFile = this . files [ 0 ] ;
} ) ;
el . querySelector ( 'button.cancel' ) . addEventListener ( 'click' , function ( ) {
el . parentElement . removeChild ( el ) ;
} ) ;
2014-11-02 22:04:24 +03:00
btnDone . addEventListener ( 'click' , ( function ( ) {
2014-11-01 15:52:31 +03:00
el . parentElement . removeChild ( el ) ;
2014-11-02 21:10:30 +03:00
if ( ! selectedFile ) {
return ;
2014-11-01 15:52:31 +03:00
}
2014-11-02 21:10:30 +03:00
2014-11-27 11:36:10 +03:00
fs . createUniqueFile ( "/nokiafileui" , selectedFile . name , selectedFile , ( function ( fileName ) {
2014-11-05 03:04:16 +03:00
var encoder = new DataEncoder ( ) ;
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "FileSelect" ) ;
encoder . put ( DataType . USHORT , "trans_id" , trans _id ) ;
encoder . put ( DataType . STRING , "result" , "OK" ) ; // Name unknown
encoder . putStart ( DataType . ARRAY , "unknown_array" ) ; // Name unknown
encoder . putStart ( DataType . STRUCT , "unknown_struct" ) ; // Name unknown
encoder . put ( DataType . STRING , "unknown_string_1" , "" ) ; // Name and value unknown
encoder . put ( DataType . WSTRING , "unknown_string_2" , "" ) ; // Name and value unknown
encoder . put ( DataType . WSTRING , "unknown_string_3" , "nokiafileui/" + fileName ) ; // Name unknown
encoder . put ( DataType . BOOLEAN , "unknown_boolean" , 1 ) ; // Name and value unknown
encoder . put ( DataType . ULONG , "unknown_long" , 0 ) ; // Name and value unknown
encoder . putEnd ( DataType . STRUCT , "unknown_struct" ) ; // Name unknown
encoder . putEnd ( DataType . ARRAY , "unknown_array" ) ; // Name unknown
encoder . putEnd ( DataType . STRUCT , "event" ) ;
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
2014-11-02 21:10:30 +03:00
} ) ;
2014-11-05 03:04:16 +03:00
} ) . bind ( this ) ) ;
2014-11-02 21:10:30 +03:00
} ) . bind ( this ) ) ;
2014-11-01 15:52:31 +03:00
document . body . appendChild ( el ) ;
2014-10-31 13:30:09 +03:00
break ;
default :
2014-11-04 15:09:56 +03:00
console . error ( "(nokia.file-ui) event " + name + " not implemented " +
2014-10-31 13:30:09 +03:00
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
return ;
}
} ;
2014-11-04 16:59:27 +03:00
var NokiaImageProcessingLocalMsgConnection = function ( ) {
LocalMsgConnection . call ( this ) ;
} ;
NokiaImageProcessingLocalMsgConnection . prototype = Object . create ( LocalMsgConnection . prototype ) ;
NokiaImageProcessingLocalMsgConnection . prototype . sendMessageToServer = function ( message ) {
var decoder = new DataDecoder ( message . data , message . offset , message . length ) ;
decoder . getStart ( DataType . STRUCT ) ;
var name = decoder . getValue ( DataType . METHOD ) ;
switch ( name ) {
case "Common" :
var encoder = new DataEncoder ( ) ;
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Common" ) ;
encoder . putStart ( DataType . STRUCT , "message" ) ;
encoder . put ( DataType . METHOD , "name" , "ProtocolVersion" ) ;
2014-11-26 05:23:45 +03:00
encoder . put ( DataType . STRING , "version" , "1.0" ) ;
2014-11-04 16:59:27 +03:00
encoder . putEnd ( DataType . STRUCT , "message" ) ;
encoder . putEnd ( DataType . STRUCT , "event" ) ;
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
break ;
case "Scale" :
var trans _id = decoder . getValue ( DataType . BYTE ) ;
var fileName = decoder . getValue ( DataType . WSTRING ) ;
2014-11-26 05:23:45 +03:00
var max _vres = 0 ;
var max _hres = 0 ;
var max _kb = 0 ;
2014-11-04 16:59:27 +03:00
decoder . getStart ( DataType . LIST ) ;
2014-11-26 05:23:45 +03:00
while ( true ) {
var paramName = decoder . getName ( ) ;
var value = decoder . getValue ( DataType . USHORT ) ;
if ( paramName === "limits" )
break ;
switch ( paramName ) {
case "max_kb" :
max _kb = value ;
break ;
case "max_vres" :
max _vres = value ;
break ;
case "max_hres" :
max _hres = value ;
break ;
default :
console . error ( "(nokia.image-processing) event " + name + " with " +
paramName + " = " + value + " not implemented." ) ;
return ;
}
2014-11-04 16:59:27 +03:00
}
decoder . getEnd ( DataType . LIST ) ;
var aspect = decoder . getValue ( DataType . STRING ) ;
2014-11-26 05:23:45 +03:00
var quality = decoder . getValue ( DataType . BYTE ) || 80 ;
2014-11-04 16:59:27 +03:00
2014-11-07 12:39:55 +03:00
if ( aspect != "FullImage" && aspect != "LockToPartialView" ) {
2014-11-08 00:27:58 +03:00
console . error ( "(nokia.image-processing) event " + name + " with aspect != 'FullImage' or 'LockToPartialView' not implemented " +
2014-11-05 02:48:03 +03:00
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
return ;
}
2014-11-05 03:08:30 +03:00
fs . open ( "/" + fileName , ( function ( fd ) {
2014-11-26 05:23:45 +03:00
var _sendBackScaledImage = function ( blob ) {
2014-11-27 11:36:10 +03:00
fs . createUniqueFile ( "/nokiaimageprocessing" , "image" , blob , ( function ( fileName ) {
2014-11-26 05:23:45 +03:00
var encoder = new DataEncoder ( ) ;
encoder . putStart ( DataType . STRUCT , "event" ) ;
encoder . put ( DataType . METHOD , "name" , "Scale" ) ;
encoder . put ( DataType . BYTE , "trans_id" , trans _id ) ;
encoder . put ( DataType . STRING , "result" , "Complete" ) ; // Name unknown
encoder . put ( DataType . WSTRING , "filename" , "nokiaimageprocessing/" + fileName ) ; // Name unknown
encoder . putEnd ( DataType . STRUCT , "event" ) ;
var data = new TextEncoder ( ) . encode ( encoder . getData ( ) ) ;
this . sendMessageToClient ( {
data : data ,
length : data . length ,
offset : 0 ,
} ) ;
} ) . bind ( this ) ) ;
} . bind ( this ) ;
2014-11-04 18:05:27 +03:00
var imgData = fs . read ( fd ) ;
2014-11-26 05:23:45 +03:00
var fileSize = fs . getsize ( fd ) ;
2014-11-04 18:05:27 +03:00
fs . close ( fd ) ;
var img = new Image ( ) ;
img . src = URL . createObjectURL ( new Blob ( [ imgData ] ) ) ;
2014-11-05 03:08:30 +03:00
img . onload = ( function ( ) {
2014-11-26 05:23:45 +03:00
// If the image size is less than the given max_kb, and height/width
// are less than max_hres/max_wres, send the original image immediately
// without any scaling.
if ( max _kb > 0 && ( max _kb * 1024 ) >= fileSize &&
( max _hres <= 0 || img . naturalHeight <= max _vres ) &&
( max _vres <= 0 || img . naturalWidth <= max _hres ) ) {
_sendBackScaledImage ( new Blob ( [ imgData ] ) ) ;
return ;
}
function _imageToBlob ( aCanvas , aImage , aHeight , aWidth , aQuality ) {
aCanvas . width = aWidth ;
aCanvas . height = aHeight ;
var ctx = aCanvas . getContext ( "2d" ) ;
ctx . drawImage ( aImage , 0 , 0 , aWidth , aHeight ) ;
return new Promise ( function ( resolve , reject ) {
aCanvas . toBlob ( resolve , "image/jpeg" , aQuality / 100 ) ;
} ) ;
}
2014-11-05 02:47:29 +03:00
var canvas = document . createElement ( "canvas" ) ;
2014-11-26 05:23:45 +03:00
if ( max _kb <= 0 ) {
_imageToBlob ( canvas , img , Math . min ( img . naturalHeight , max _vres ) ,
Math . min ( img . naturalWidth , max _hres ) , quality ) . then ( _sendBackScaledImage ) ;
return ;
}
_imageToBlob ( canvas , img , img . naturalHeight ,
img . naturalWidth , quality ) . then ( function ( blob ) {
var imgSizeInKb = blob . size / 1024 ;
// Roughly recalc max_vres and max_hres based on the max_kb and the real resolution.
var ratio = Math . sqrt ( max _kb / imgSizeInKb ) ;
max _hres = Math . min ( img . naturalWidth * ratio ,
max _hres <= 0 ? img . naturalWidth : max _hres ) ;
max _vres = Math . min ( img . naturalHeight * ratio ,
max _vres <= 0 ? img . naturalHeight : max _vres ) ;
return _imageToBlob ( canvas , img , Math . min ( img . naturalHeight , max _vres ) ,
Math . min ( img . naturalWidth , max _hres ) , quality ) ;
} ) . then ( _sendBackScaledImage ) ;
2014-11-02 21:10:30 +03:00
} ) . bind ( this ) ;
2014-11-05 03:08:30 +03:00
img . onerror = function ( e ) {
console . error ( "Error in decoding image" ) ;
} ;
2014-11-02 21:10:30 +03:00
} ) . bind ( this ) ) ;
2014-10-31 13:30:09 +03:00
break ;
default :
2014-11-04 16:59:27 +03:00
console . error ( "(nokia.image-processing) event " + name + " not implemented " +
2014-10-31 13:30:09 +03:00
util . decodeUtf8 ( new Uint8Array ( message . data . buffer , message . offset , message . length ) ) ) ;
return ;
}
} ;
2014-08-29 01:04:17 +04:00
MIDP . LocalMsgConnections = { } ;
2014-09-06 03:00:48 +04:00
// Add some fake servers because some MIDlets assume they exist.
2014-09-06 03:05:35 +04:00
// MIDlets are usually happy even if the servers don't reply, but we should
// remember to implement them in case they will be needed.
2014-10-14 13:18:38 +04:00
MIDP . FakeLocalMsgServers = [ "nokia.active-standby" , "nokia.profile" ,
2014-11-04 16:59:27 +03:00
"nokia.connectivity-settings" ] ;
2014-09-20 03:43:21 +04:00
2014-09-06 04:01:30 +04:00
MIDP . FakeLocalMsgServers . forEach ( function ( server ) {
2014-11-27 11:36:10 +03:00
MIDP . LocalMsgConnections [ server ] = LocalMsgConnection ;
2014-09-06 04:01:30 +04:00
} ) ;
2014-08-29 01:04:17 +04:00
2014-11-27 11:36:10 +03:00
MIDP . LocalMsgConnections [ "nokia.contacts" ] = NokiaContactsLocalMsgConnection ;
MIDP . LocalMsgConnections [ "nokia.messaging" ] = NokiaMessagingLocalMsgConnection ;
MIDP . LocalMsgConnections [ "nokia.phone-status" ] = NokiaPhoneStatusLocalMsgConnection ;
MIDP . LocalMsgConnections [ "nokia.file-ui" ] = NokiaFileUILocalMsgConnection ;
MIDP . LocalMsgConnections [ "nokia.image-processing" ] = NokiaImageProcessingLocalMsgConnection ;
MIDP . LocalMsgConnections [ "nokia.sa.service-registry" ] = NokiaSASrvRegLocalMsgConnection ;
2014-09-10 03:07:40 +04:00
2014-10-27 14:37:53 +03:00
Native . create ( "org/mozilla/io/LocalMsgConnection.init.(Ljava/lang/String;)V" , function ( jName ) {
2014-10-15 02:45:53 +04:00
var name = util . fromJavaString ( jName ) ;
2014-08-29 01:04:17 +04:00
2014-10-15 02:45:53 +04:00
this . server = ( name [ 2 ] == ":" ) ;
this . protocolName = name . slice ( ( name [ 2 ] == ':' ) ? 3 : 2 ) ;
2014-10-17 07:08:51 +04:00
return new Promise ( ( function ( resolve , reject ) {
if ( this . server ) {
2014-11-27 11:36:10 +03:00
// It seems that one server only serves on client at a time, let's
// store an object instead of the constructor.
this . connection = MIDP . LocalMsgConnections [ this . protocolName ] = new LocalMsgConnection ( ) ;
2014-10-17 07:08:51 +04:00
MIDP . ConnectionRegistry . pushNotify ( "localmsg:" + this . protocolName ) ;
} else {
// Actually, there should always be a server, but we need this check
// for apps that use the Nokia built-in servers (because we haven't
// implemented them yet).
if ( ! MIDP . LocalMsgConnections [ this . protocolName ] ) {
console . warn ( "localmsg server (" + this . protocolName + ") unimplemented" ) ;
// Return without resolving the promise, we want the thread that is connecting
// to this unimplemented server to stop indefinitely.
return ;
}
2014-08-29 01:04:17 +04:00
2014-10-17 07:08:51 +04:00
if ( MIDP . FakeLocalMsgServers . indexOf ( this . protocolName ) != - 1 ) {
console . warn ( "connect to an unimplemented localmsg server (" + this . protocolName + ")" ) ;
}
2014-11-27 11:36:10 +03:00
this . connection = typeof MIDP . LocalMsgConnections [ this . protocolName ] === 'function' ?
new MIDP . LocalMsgConnections [ this . protocolName ] ( ) : MIDP . LocalMsgConnections [ this . protocolName ] ;
this . connection . notifyConnection ( ) ;
2014-09-06 04:01:30 +04:00
}
2014-10-17 07:08:51 +04:00
resolve ( ) ;
} ) . bind ( this ) ) ;
2014-11-04 04:47:51 +03:00
} , true ) ;
2014-08-29 01:04:17 +04:00
2014-10-27 14:37:53 +03:00
Native . create ( "org/mozilla/io/LocalMsgConnection.waitConnection.()V" , function ( ) {
2014-11-27 11:36:10 +03:00
return this . connection . waitConnection ( ) ;
2014-10-15 02:45:53 +04:00
} ) ;
2014-08-29 01:04:17 +04:00
2014-10-27 14:37:53 +03:00
Native . create ( "org/mozilla/io/LocalMsgConnection.sendData.([BII)V" , function ( data , offset , length ) {
2014-08-29 01:04:17 +04:00
var message = {
data : data ,
offset : offset ,
length : length ,
} ;
2014-10-15 02:45:53 +04:00
if ( this . server ) {
2014-11-27 11:36:10 +03:00
this . connection . sendMessageToClient ( message ) ;
2014-08-29 01:04:17 +04:00
} else {
2014-10-15 02:45:53 +04:00
if ( MIDP . FakeLocalMsgServers . indexOf ( this . protocolName ) != - 1 ) {
console . warn ( "sendData (" + util . decodeUtf8 ( new Uint8Array ( data . buffer , offset , length ) ) + ") to an unimplemented localmsg server (" + this . protocolName + ")" ) ;
2014-09-06 04:01:30 +04:00
}
2014-11-27 11:36:10 +03:00
this . connection . sendMessageToServer ( message ) ;
2014-08-29 01:04:17 +04:00
}
2014-10-15 02:45:53 +04:00
} ) ;
2014-08-29 01:04:17 +04:00
2014-10-27 14:37:53 +03:00
Native . create ( "org/mozilla/io/LocalMsgConnection.receiveData.([B)I" , function ( data ) {
2014-10-17 02:04:31 +04:00
if ( this . server ) {
2014-11-27 11:36:10 +03:00
return this . connection . serverReceiveMessage ( data ) ;
2014-10-17 02:04:31 +04:00
}
2014-09-06 04:01:30 +04:00
2014-10-17 02:04:31 +04:00
if ( MIDP . FakeLocalMsgServers . indexOf ( this . protocolName ) != - 1 ) {
console . warn ( "receiveData from an unimplemented localmsg server (" + this . protocolName + ")" ) ;
2014-08-29 01:04:17 +04:00
}
2014-10-17 02:04:31 +04:00
2014-11-27 11:36:10 +03:00
return this . connection . clientReceiveMessage ( data ) ;
2014-11-04 04:47:51 +03:00
} , true ) ;
2014-08-29 01:04:17 +04:00
2014-10-27 14:37:53 +03:00
Native . create ( "org/mozilla/io/LocalMsgConnection.closeConnection.()V" , function ( ) {
2014-10-15 02:45:53 +04:00
if ( this . server ) {
delete MIDP . LocalMsgConnections [ this . protocolName ] ;
2014-08-29 01:04:17 +04:00
}
2014-11-27 11:36:10 +03:00
delete this . connection ;
2014-10-15 02:45:53 +04:00
} ) ;