Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
9d77a4ef
Commit
9d77a4ef
authored
Nov 18, 2018
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes #129 Add support for XEP-0156.
Only XML is supported for now.
parent
54e9c51a
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
335 additions
and
263 deletions
+335
-263
CHANGES.md
CHANGES.md
+7
-0
docs/source/configuration.rst
docs/source/configuration.rst
+18
-2
spec/bookmarks.js
spec/bookmarks.js
+24
-61
spec/login.js
spec/login.js
+2
-2
spec/register.js
spec/register.js
+11
-11
spec/roomslist.js
spec/roomslist.js
+2
-4
spec/smacks.js
spec/smacks.js
+1
-1
src/converse-chatview.js
src/converse-chatview.js
+1
-1
src/converse-controlbox.js
src/converse-controlbox.js
+15
-13
src/converse-dragresize.js
src/converse-dragresize.js
+1
-1
src/converse-minimize.js
src/converse-minimize.js
+2
-5
src/converse-omemo.js
src/converse-omemo.js
+2
-2
src/converse-register.js
src/converse-register.js
+4
-3
src/headless/converse-bosh.js
src/headless/converse-bosh.js
+18
-13
src/headless/converse-chatboxes.js
src/headless/converse-chatboxes.js
+2
-2
src/headless/converse-core.js
src/headless/converse-core.js
+144
-65
src/headless/converse-muc.js
src/headless/converse-muc.js
+1
-1
src/headless/utils/core.js
src/headless/utils/core.js
+9
-0
tests/mock.js
tests/mock.js
+71
-76
No files found.
CHANGES.md
View file @
9d77a4ef
...
...
@@ -2,11 +2,18 @@
## 6.0.0 (Unreleased)
-
#129: Add support for XEP-0156: Disovering Alternative XMPP Connection Methods. Only XML is supported for now.
-
#1691 Fix
`collection.chatbox is undefined`
errors
-
Prevent editing of sent file uploads.
### Breaking changes
-
In order to add support for XEP-0156, the XMPP connection needs to be created
only once we know the JID of the user that's logging in. This means that the
[
connectionInitialized
](
https://conversejs.org/docs/html/api/-_converse.html#event:connectionInitialized
)
event now fires much later than before. Plugins that rely on
`connectionInitialized`
being triggered before the user's JID has been provided will need to be updated.
-
The following API methods now return promises:
*
`_converse.api.chats.get`
*
`_converse.api.chats.create`
...
...
docs/source/configuration.rst
View file @
9d77a4ef
...
...
@@ -639,6 +639,23 @@ The default chat status that the user wil have. If you for example set this to
``'chat'``, then Converse will send out a presence stanza with ``"show"``
set to ``'chat'`` as soon as you've been logged in.
discover_connection_methods
---------------------------
* Default: ``false``
Use `XEP-0156 <https://xmpp.org/extensions/xep-0156.html>`_ to discover whether
the XMPP host for the current user advertises any Websocket or BOSH connection
URLs that can be used.
If this is set to ``false``, then a `websocket_url`_ or `bosh_service_url`_ need to be
set.
Currently only the XML encoded host-meta resource is supported as shown in
`Example 2 under section 3.3 <https://xmpp.org/extensions/xep-0156.html#httpexamples>`_.
domain_placeholder
------------------
...
...
@@ -647,8 +664,6 @@ domain_placeholder
The placeholder text shown in the domain input on the registration form.
emoji_image_path
----------------
...
...
@@ -1624,6 +1639,7 @@ Allows you to show or hide buttons on the chatboxes' toolbars.
.. _`websocket-url`:
websocket_url
-------------
...
...
spec/bookmarks.js
View file @
9d77a4ef
...
...
@@ -404,7 +404,7 @@
it
(
"
can be retrieved from the XMPP server
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
[
'
chatBoxesFetched
'
,
'
roomsPanelRendered
'
,
'
rosterGroupsFetched
'
],
{},
null
,
[
'
chatBoxesFetched
'
,
'
roomsPanelRendered
'
,
'
rosterGroupsFetched
'
],
{},
async
function
(
done
,
_converse
)
{
await
test_utils
.
waitUntilDiscoConfirmed
(
...
...
@@ -421,25 +421,12 @@
* </pubsub>
* </iq>
*/
let
IQ_id
;
const
call
=
await
u
.
waitUntil
(()
=>
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
call
=>
{
const
stanza
=
call
.
args
[
0
];
if
(
!
(
stanza
instanceof
Element
)
||
stanza
.
nodeName
!==
'
iq
'
)
{
return
;
}
if
(
sizzle
(
'
items[node="storage:bookmarks"]
'
,
stanza
).
length
)
{
IQ_id
=
stanza
.
getAttribute
(
'
id
'
);
return
true
;
}
}
).
pop
()
);
const
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
const
sent_stanza
=
await
u
.
waitUntil
(
()
=>
IQ_stanzas
.
filter
(
s
=>
sizzle
(
'
items[node="storage:bookmarks"]
'
,
s
).
length
).
pop
());
expect
(
Strophe
.
serialize
(
call
.
args
[
0
]
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
IQ_id
}
" type="get" xmlns="jabber:client">`
+
expect
(
Strophe
.
serialize
(
sent_stanza
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
sent_stanza
.
getAttribute
(
'
id
'
)
}
" type="get" xmlns="jabber:client">`
+
'
<pubsub xmlns="http://jabber.org/protocol/pubsub">
'
+
'
<items node="storage:bookmarks"/>
'
+
'
</pubsub>
'
+
...
...
@@ -469,7 +456,7 @@
expect
(
_converse
.
bookmarks
.
models
.
length
).
toBe
(
0
);
spyOn
(
_converse
.
bookmarks
,
'
onBookmarksReceived
'
).
and
.
callThrough
();
var
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
})
var
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
sent_stanza
.
getAttribute
(
'
id
'
)
})
.
c
(
'
pubsub
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
PUBSUB
})
.
c
(
'
items
'
,
{
'
node
'
:
'
storage:bookmarks
'
})
.
c
(
'
item
'
,
{
'
id
'
:
'
current
'
})
...
...
@@ -495,7 +482,7 @@
describe
(
"
The rooms panel
"
,
function
()
{
it
(
"
shows a list of bookmarks
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
],
{},
async
function
(
done
,
_converse
)
{
await
test_utils
.
waitUntilDiscoConfirmed
(
...
...
@@ -505,31 +492,19 @@
);
test_utils
.
openControlBox
();
let
IQ_id
;
const
call
=
await
u
.
waitUntil
(()
=>
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
call
=>
{
const
stanza
=
call
.
args
[
0
];
if
(
!
(
stanza
instanceof
Element
)
||
stanza
.
nodeName
!==
'
iq
'
)
{
return
;
}
if
(
sizzle
(
'
items[node="storage:bookmarks"]
'
,
stanza
).
length
)
{
IQ_id
=
stanza
.
getAttribute
(
'
id
'
);
return
true
;
}
}
).
pop
()
);
expect
(
Strophe
.
serialize
(
call
.
args
[
0
])).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
IQ_id
}
" type="get" xmlns="jabber:client">`
+
const
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
const
sent_stanza
=
await
u
.
waitUntil
(
()
=>
IQ_stanzas
.
filter
(
s
=>
sizzle
(
'
items[node="storage:bookmarks"]
'
,
s
).
length
).
pop
());
expect
(
Strophe
.
serialize
(
sent_stanza
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
sent_stanza
.
getAttribute
(
'
id
'
)}
" type="get" xmlns="jabber:client">`
+
'
<pubsub xmlns="http://jabber.org/protocol/pubsub">
'
+
'
<items node="storage:bookmarks"/>
'
+
'
</pubsub>
'
+
'
</iq>
'
);
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
})
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
sent_stanza
.
getAttribute
(
'
id
'
)
})
.
c
(
'
pubsub
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
PUBSUB
})
.
c
(
'
items
'
,
{
'
node
'
:
'
storage:bookmarks
'
})
.
c
(
'
item
'
,
{
'
id
'
:
'
current
'
})
...
...
@@ -583,7 +558,7 @@
it
(
"
remembers the toggle state of the bookmarks list
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
],
{},
async
function
(
done
,
_converse
)
{
test_utils
.
openControlBox
();
...
...
@@ -593,31 +568,19 @@
[
'
http://jabber.org/protocol/pubsub#publish-options
'
]
);
let
IQ_id
;
const
call
=
await
u
.
waitUntil
(()
=>
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
call
=>
{
const
stanza
=
call
.
args
[
0
];
if
(
!
(
stanza
instanceof
Element
)
||
stanza
.
nodeName
!==
'
iq
'
)
{
return
;
}
if
(
sizzle
(
'
items[node="storage:bookmarks"]
'
,
stanza
).
length
)
{
IQ_id
=
stanza
.
getAttribute
(
'
id
'
);
return
true
;
}
}
).
pop
()
);
expect
(
Strophe
.
serialize
(
call
.
args
[
0
])).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
IQ_id
}
" type="get" xmlns="jabber:client">`
+
const
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
const
sent_stanza
=
await
u
.
waitUntil
(
()
=>
IQ_stanzas
.
filter
(
s
=>
sizzle
(
'
items[node="storage:bookmarks"]
'
,
s
).
length
).
pop
());
expect
(
Strophe
.
serialize
(
sent_stanza
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
sent_stanza
.
getAttribute
(
'
id
'
)}
" type="get" xmlns="jabber:client">`
+
'
<pubsub xmlns="http://jabber.org/protocol/pubsub">
'
+
'
<items node="storage:bookmarks"/>
'
+
'
</pubsub>
'
+
'
</iq>
'
);
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
})
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
sent_stanza
.
getAttribute
(
'
id
'
)
})
.
c
(
'
pubsub
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
PUBSUB
})
.
c
(
'
items
'
,
{
'
node
'
:
'
storage:bookmarks
'
})
.
c
(
'
item
'
,
{
'
id
'
:
'
current
'
})
...
...
spec/login.js
View file @
9d77a4ef
...
...
@@ -8,7 +8,7 @@
it
(
"
contains a checkbox to indicate whether the computer is trusted or not
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
false
},
async
function
(
done
,
_converse
)
{
...
...
@@ -42,7 +42,7 @@
it
(
"
checkbox can be set to false by default
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
trusted
:
false
,
allow_registration
:
false
},
...
...
spec/register.js
View file @
9d77a4ef
...
...
@@ -10,7 +10,7 @@
it
(
"
is not available unless allow_registration=true
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
false
},
async
function
(
done
,
_converse
)
{
...
...
@@ -24,7 +24,7 @@
it
(
"
can be opened by clicking on the registration tab
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
...
...
@@ -45,18 +45,18 @@
it
(
"
allows the user to choose an XMPP provider's domain
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
spyOn
(
Strophe
.
Connection
.
prototype
,
'
connect
'
);
await
u
.
waitUntil
(()
=>
_
.
get
(
_converse
.
chatboxviews
.
get
(
'
controlbox
'
),
'
registerpanel
'
));
test_utils
.
openControlBox
();
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
const
registerview
=
cbview
.
registerpanel
;
spyOn
(
registerview
,
'
onProviderChosen
'
).
and
.
callThrough
();
registerview
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
spyOn
(
_converse
.
connection
,
'
connect
'
);
// Open the register panel
cbview
.
el
.
querySelector
(
'
.toggle-register-login
'
).
click
();
...
...
@@ -75,17 +75,18 @@
form
.
querySelector
(
'
input[name=domain]
'
).
value
=
'
conversejs.org
'
;
submit_button
.
click
();
expect
(
registerview
.
onProviderChosen
).
toHaveBeenCalled
();
expect
(
_converse
.
connection
.
connect
).
toHaveBeenCalled
(
);
await
u
.
waitUntil
(()
=>
_converse
.
connection
.
connect
.
calls
.
count
()
);
done
();
}));
it
(
"
will render a registration form as received from the XMPP provider
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
spyOn
(
Strophe
.
Connection
.
prototype
,
'
connect
'
);
await
u
.
waitUntil
(()
=>
_
.
get
(
_converse
.
chatboxviews
.
get
(
'
controlbox
'
),
'
registerpanel
'
));
test_utils
.
openControlBox
();
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
...
...
@@ -97,7 +98,6 @@
spyOn
(
registerview
,
'
onRegistrationFields
'
).
and
.
callThrough
();
spyOn
(
registerview
,
'
renderRegistrationForm
'
).
and
.
callThrough
();
registerview
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
spyOn
(
_converse
.
connection
,
'
connect
'
).
and
.
callThrough
();
expect
(
registerview
.
_registering
).
toBeFalsy
();
expect
(
_converse
.
connection
.
connected
).
toBeFalsy
();
...
...
@@ -105,7 +105,7 @@
registerview
.
el
.
querySelector
(
'
input[type=submit]
'
).
click
();
expect
(
registerview
.
onProviderChosen
).
toHaveBeenCalled
();
expect
(
registerview
.
_registering
).
toBeTruthy
();
expect
(
_converse
.
connection
.
connect
).
toHaveBeenCalled
(
);
await
u
.
waitUntil
(()
=>
_converse
.
connection
.
connect
.
calls
.
count
()
);
let
stanza
=
new
Strophe
.
Builder
(
"
stream:features
"
,
{
'
xmlns:stream
'
:
"
http://etherx.jabber.org/streams
"
,
...
...
@@ -137,7 +137,7 @@
it
(
"
will set form_type to legacy and submit it as legacy
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
...
...
@@ -194,7 +194,7 @@
it
(
"
will set form_type to xform and submit it as xform
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
...
...
@@ -267,7 +267,7 @@
it
(
"
renders the account registration form
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
view_mode
:
'
fullscreen
'
,
allow_registration
:
true
},
...
...
spec/roomslist.js
View file @
9d77a4ef
...
...
@@ -53,7 +53,7 @@
it
(
"
uses bookmarks to determine groupchat names
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
,
'
emojisInitialized
'
],
{
'
view_mode
'
:
'
fullscreen
'
},
async
function
(
done
,
_converse
)
{
...
...
@@ -113,7 +113,7 @@
describe
(
"
A groupchat shown in the groupchats list
"
,
function
()
{
it
(
"
is highlighted if its currently open
"
,
mock
.
initConverse
(
it
(
"
is highlighted if it
'
s currently open
"
,
mock
.
initConverse
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
,
'
emojisInitialized
'
],
{
view_mode
:
'
fullscreen
'
,
allow_bookmarks
:
false
// Makes testing easier, otherwise we have to mock stanza traffic.
...
...
@@ -137,8 +137,6 @@
expect
(
room_els
.
length
).
toBe
(
1
);
item
=
room_els
[
0
];
expect
(
item
.
textContent
.
trim
()).
toBe
(
'
balcony@chat.shakespeare.lit
'
);
const
conv_el
=
document
.
querySelector
(
'
#conversejs
'
);
conv_el
.
parentElement
.
removeChild
(
conv_el
);
done
();
}));
...
...
spec/smacks.js
View file @
9d77a4ef
...
...
@@ -11,7 +11,7 @@
it
(
"
gets enabled with an <enable> stanza and resumed with a <resume> stanza
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
'
auto_login
'
:
false
,
'
enable_smacks
'
:
true
,
'
show_controlbox_by_default
'
:
true
,
...
...
src/converse-chatview.js
View file @
9d77a4ef
...
...
@@ -1124,7 +1124,7 @@ converse.plugins.add('converse-chatview', {
if
(
Backbone
.
history
.
getFragment
()
===
"
converse/chat?jid=
"
+
this
.
model
.
get
(
'
jid
'
))
{
_converse
.
router
.
navigate
(
''
);
}
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
// Immediately sending the chat state, because the
// model is going to be destroyed afterwards.
this
.
model
.
setChatState
(
_converse
.
INACTIVE
);
...
...
src/converse-controlbox.js
View file @
9d77a4ef
...
...
@@ -154,6 +154,7 @@ converse.plugins.add('converse-controlbox', {
_converse
.
api
.
promises
.
add
(
'
controlBoxInitialized
'
);
const
addControlBox
=
()
=>
_converse
.
chatboxes
.
add
({
'
id
'
:
'
controlbox
'
});
_converse
.
ControlBox
=
_converse
.
ChatBox
.
extend
({
...
...
@@ -220,9 +221,9 @@ converse.plugins.add('converse-controlbox', {
}
else
{
this
.
hide
();
}
if
(
!
_converse
.
connection
.
connected
||
!
_converse
.
connection
.
authenticated
||
_converse
.
connection
.
disconnecting
)
{
const
connection
=
get
(
_converse
,
'
connection
'
,
{});
if
(
!
connection
.
connected
||
!
connection
.
authenticated
||
connection
.
disconnecting
)
{
this
.
renderLoginPanel
();
}
else
if
(
this
.
model
.
get
(
'
connected
'
))
{
this
.
renderControlBoxPane
();
...
...
@@ -296,7 +297,8 @@ converse.plugins.add('converse-controlbox', {
if
(
_converse
.
sticky_controlbox
)
{
return
;
}
if
(
_converse
.
connection
.
connected
&&
!
_converse
.
connection
.
disconnecting
)
{
const
connection
=
get
(
_converse
,
'
connection
'
,
{});
if
(
connection
.
connected
&&
!
connection
.
disconnecting
)
{
this
.
model
.
save
({
'
closed
'
:
true
});
}
else
{
this
.
model
.
trigger
(
'
hide
'
);
...
...
@@ -319,7 +321,8 @@ converse.plugins.add('converse-controlbox', {
}
u
.
addClass
(
'
hidden
'
,
this
.
el
);
_converse
.
api
.
trigger
(
'
chatBoxClosed
'
,
this
);
if
(
!
_converse
.
connection
.
connected
)
{
if
(
!
_converse
.
api
.
connection
.
connected
())
{
_converse
.
controlboxtoggle
.
render
();
}
_converse
.
controlboxtoggle
.
show
(
callback
);
...
...
@@ -464,7 +467,7 @@ converse.plugins.add('converse-controlbox', {
if
([
"
converse/login
"
,
"
converse/register
"
].
includes
(
Backbone
.
history
.
getFragment
()))
{
_converse
.
router
.
navigate
(
''
,
{
'
replace
'
:
true
});
}
_converse
.
connection
.
reset
();
_converse
.
connection
&&
_converse
.
connection
.
reset
();
_converse
.
api
.
user
.
login
(
jid
,
password
);
}
});
...
...
@@ -510,7 +513,7 @@ converse.plugins.add('converse-controlbox', {
// artifacts (i.e. on page load the toggle is shown only to then
// seconds later be hidden in favor of the controlbox).
this
.
el
.
innerHTML
=
tpl_controlbox_toggle
({
'
label_toggle
'
:
_converse
.
connection
.
connected
?
__
(
'
Chat Contacts
'
)
:
__
(
'
Toggle chat
'
)
'
label_toggle
'
:
_converse
.
api
.
connection
.
connected
()
?
__
(
'
Chat Contacts
'
)
:
__
(
'
Toggle chat
'
)
})
return
this
;
},
...
...
@@ -529,7 +532,7 @@ converse.plugins.add('converse-controlbox', {
if
(
!
controlbox
)
{
controlbox
=
addControlBox
();
}
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
controlbox
.
save
({
'
closed
'
:
false
});
}
else
{
controlbox
.
trigger
(
'
show
'
);
...
...
@@ -540,7 +543,7 @@ converse.plugins.add('converse-controlbox', {
e
.
preventDefault
();
if
(
u
.
isVisible
(
_converse
.
root
.
querySelector
(
"
#controlbox
"
)))
{
const
controlbox
=
_converse
.
chatboxes
.
get
(
'
controlbox
'
);
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
)
{
controlbox
.
save
({
closed
:
true
});
}
else
{
controlbox
.
trigger
(
'
hide
'
);
...
...
@@ -582,10 +585,9 @@ converse.plugins.add('converse-controlbox', {
});
Promise
.
all
([
_converse
.
api
.
waitUntil
(
'
connectionInitialized
'
),
_converse
.
api
.
waitUntil
(
'
chatBoxViewsInitialized
'
)
]).
then
(
addControlBox
).
catch
(
e
=>
_converse
.
log
(
e
,
Strophe
.
LogLevel
.
FATAL
));
.
then
(
addControlBox
)
.
catch
(
e
=>
_converse
.
log
(
e
,
Strophe
.
LogLevel
.
FATAL
));
_converse
.
api
.
listen
.
on
(
'
chatBoxesFetched
'
,
()
=>
{
const
controlbox
=
_converse
.
chatboxes
.
get
(
'
controlbox
'
)
||
addControlBox
();
...
...
src/converse-dragresize.js
View file @
9d77a4ef
...
...
@@ -351,7 +351,7 @@ converse.plugins.add('converse-dragresize', {
_converse
.
resizing
.
chatbox
.
width
,
_converse
.
resizing
.
chatbox
.
model
.
get
(
'
default_width
'
)
);
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
_converse
.
resizing
.
chatbox
.
model
.
save
({
'
height
'
:
height
});
_converse
.
resizing
.
chatbox
.
model
.
save
({
'
width
'
:
width
});
}
else
{
...
...
src/converse-minimize.js
View file @
9d77a4ef
...
...
@@ -318,7 +318,7 @@ converse.plugins.add('converse-minimize', {
* @param { _converse.ChatBoxView|_converse.ChatRoomView|_converse.ControlBoxView|_converse.HeadlinesBoxView } [newchat]
*/
async
trimChats
(
newchat
)
{
if
(
_converse
.
no_trimming
||
!
_converse
.
connection
.
connected
||
_converse
.
view_mode
!==
'
overlayed
'
)
{
if
(
_converse
.
no_trimming
||
!
_converse
.
api
.
connection
.
connected
()
||
_converse
.
view_mode
!==
'
overlayed
'
)
{
return
;
}
const
shown_chats
=
this
.
getShownChats
();
...
...
@@ -556,10 +556,7 @@ converse.plugins.add('converse-minimize', {
});
/************************ BEGIN Event Handlers ************************/
Promise
.
all
([
_converse
.
api
.
waitUntil
(
'
connectionInitialized
'
),
_converse
.
api
.
waitUntil
(
'
chatBoxViewsInitialized
'
)
]).
then
(()
=>
{
_converse
.
api
.
waitUntil
(
'
chatBoxViewsInitialized
'
).
then
(()
=>
{
_converse
.
minimized_chats
=
new
_converse
.
MinimizedChats
({
model
:
_converse
.
chatboxes
});
...
...
src/converse-omemo.js
View file @
9d77a4ef
...
...
@@ -240,8 +240,8 @@ converse.plugins.add('converse-omemo', {
/* The initialize function gets called as soon as the plugin is
* loaded by Converse.js's plugin machinery.
*/
const
{
_converse
}
=
this
,
{
__
}
=
_converse
;
const
{
_converse
}
=
this
;
const
{
__
}
=
_converse
;
_converse
.
api
.
settings
.
update
({
'
omemo_default
'
:
false
,
...
...
src/converse-register.js
View file @
9d77a4ef
...
...
@@ -175,7 +175,7 @@ converse.plugins.add('converse-register', {
initialize
()
{
this
.
reset
();
this
.
registerHooks
(
);
_converse
.
api
.
listen
.
on
(
'
connectionInitialized
'
,
()
=>
this
.
registerHooks
()
);
},
render
()
{
...
...
@@ -340,7 +340,7 @@ converse.plugins.add('converse-register', {
* @method _converse.RegisterPanel#fetchRegistrationForm
* @param { String } domain_name - XMPP server domain
*/
fetchRegistrationForm
(
domain_name
)
{
async
fetchRegistrationForm
(
domain_name
)
{
if
(
!
this
.
model
.
get
(
'
registration_form_rendered
'
))
{
this
.
renderRegistrationRequest
();
}
...
...
@@ -348,7 +348,8 @@ converse.plugins.add('converse-register', {
'
domain
'
:
Strophe
.
getDomainFromJid
(
domain_name
),
'
_registering
'
:
true
});
_converse
.
connection
.
connect
(
this
.
domain
,
""
,
this
.
onConnectStatusChanged
.
bind
(
this
));
await
_converse
.
initConnection
(
this
.
domain
);
_converse
.
connection
.
connect
(
this
.
domain
,
""
,
status
=>
this
.
onConnectStatusChanged
(
status
));
return
false
;
},
...
...
src/headless/converse-bosh.js
View file @
9d77a4ef
...
...
@@ -19,6 +19,10 @@ const BOSH_SESSION_ID = 'converse.bosh-session';
converse
.
plugins
.
add
(
'
converse-bosh
'
,
{
enabled
()
{
return
true
;
},
initialize
()
{
const
{
_converse
}
=
this
;
...
...
@@ -35,9 +39,15 @@ converse.plugins.add('converse-bosh', {
_converse
.
bosh_session
.
browserStorage
=
new
BrowserStorage
.
session
(
id
);
await
new
Promise
(
resolve
=>
_converse
.
bosh_session
.
fetch
({
'
success
'
:
resolve
,
'
error
'
:
resolve
}));
}
if
(
_converse
.
jid
&&
_converse
.
bosh_session
.
get
(
'
jid
'
)
===
_converse
.
jid
)
{
if
(
_converse
.
jid
)
{
if
(
_converse
.
bosh_session
.
get
(
'
jid
'
)
!==
_converse
.
jid
)
{
const
jid
=
await
_converse
.
setUserJID
(
_converse
.
jid
);
_converse
.
bosh_session
.
clear
({
'
silent
'
:
true
});
_converse
.
bosh_session
.
save
({
'
jid
'
:
_converse
.
jid
,
id
});
_converse
.
bosh_session
.
save
({
jid
});
}
}
else
{
// Keepalive
const
jid
=
_converse
.
bosh_session
.
get
(
'
jid
'
);
jid
&&
await
_converse
.
setUserJID
();
}
return
_converse
.
bosh_session
;
}
...
...
@@ -45,17 +55,17 @@ converse.plugins.add('converse-bosh', {
_converse
.
startNewPreboundBOSHSession
=
function
()
{
if
(
!
_converse
.
prebind_url
)
{
throw
new
Error
(
"
attemptPreboundSession: If you use prebind then you MUST supply a prebind_url
"
);
throw
new
Error
(
"
startNewPreboundBOSHSession: If you use prebind then you MUST supply a prebind_url
"
);
}
const
xhr
=
new
XMLHttpRequest
();
xhr
.
open
(
'
GET
'
,
_converse
.
prebind_url
,
true
);
xhr
.
setRequestHeader
(
'
Accept
'
,
'
application/json, text/javascript
'
);
xhr
.
onload
=
function
()
{
xhr
.
onload
=
async
function
()
{
if
(
xhr
.
status
>=
200
&&
xhr
.
status
<
400
)
{
const
data
=
JSON
.
parse
(
xhr
.
responseText
);
const
jid
=
await
_converse
.
setUserJID
(
data
.
jid
);
_converse
.
connection
.
attach
(
data
.
jid
,
jid
,
data
.
sid
,
data
.
rid
,
_converse
.
onConnectStatusChanged
...
...
@@ -79,9 +89,6 @@ converse.plugins.add('converse-bosh', {
_converse
.
restoreBOSHSession
=
async
function
()
{
if
(
!
_converse
.
api
.
connection
.
isType
(
'
bosh
'
))
{
return
false
;
}
const
jid
=
(
await
initBOSHSession
()).
get
(
'
jid
'
);
if
(
jid
)
{
try
{
...
...
@@ -119,9 +126,7 @@ converse.plugins.add('converse-bosh', {
}
});
_converse
.
api
.
listen
.
on
(
'
addClientFeatures
'
,
()
=>
_converse
.
api
.
disco
.
own
.
features
.
add
(
Strophe
.
NS
.
BOSH
)
);
_converse
.
api
.
listen
.
on
(
'
addClientFeatures
'
,
()
=>
_converse
.
api
.
disco
.
own
.
features
.
add
(
Strophe
.
NS
.
BOSH
));
/************************ END Event Handlers ************************/
...
...
src/headless/converse-chatboxes.js
View file @
9d77a4ef
src/headless/converse-core.js
View file @
9d77a4ef
...
...
@@ -230,6 +230,7 @@ _converse.default_settings = {
csi_waiting_time
:
0
,
// Support for XEP-0352. Seconds before client is considered idle and CSI is sent out.
debug
:
false
,
default_state
:
'
online
'
,
discover_connection_methods
:
false
,
geouri_regex
:
/https
\:\/\/
www.openstreetmap.org
\/
.*#map=
[
0-9
]
+
\/([\-
0-9.
]
+
)\/([\-
0-9.
]
+
)\S
*/g
,
geouri_replacement
:
'
https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2
'
,
idle_presence_timeout
:
300
,
// Seconds after which an idle presence is sent
...
...
@@ -330,7 +331,7 @@ function addPromise (promise) {
}
_converse
.
isTestEnv
=
function
()
{
return
_
.
get
(
_converse
.
connection
,
'
service
'
)
===
'
jasmine tests
'
;
return
Strophe
.
Connection
.
name
===
'
MockConnection
'
;
}
...
...
@@ -457,7 +458,7 @@ async function attemptNonPreboundSession (credentials, automatic) {
}
else
if
(
!
_converse
.
isTestEnv
()
&&
window
.
PasswordCredential
)
{
connect
(
await
getLoginCredentialsFromBrowser
());
}
else
{
throw
new
Error
(
"
attemptNonPreboundSession: Could not find any credentials to log you in with!
"
);
_converse
.
log
(
"
attemptNonPreboundSession: Could not find any credentials to log in with
"
,
Strophe
.
LogLevel
.
WARN
);
}
}
else
if
([
_converse
.
ANONYMOUS
,
_converse
.
EXTERNAL
].
includes
(
_converse
.
authentication
)
&&
(
!
automatic
||
_converse
.
auto_login
))
{
connect
();
...
...
@@ -523,9 +524,7 @@ function reconnect () {
const
debouncedReconnect
=
_
.
debounce
(
reconnect
,
2000
);
_converse
.
shouldClearCache
=
function
()
{
return
!
_converse
.
config
.
get
(
'
trusted
'
)
||
_converse
.
isTestEnv
();
}
_converse
.
shouldClearCache
=
()
=>
(
!
_converse
.
config
.
get
(
'
trusted
'
)
||
_converse
.
isTestEnv
());
function
clearSession
()
{
if
(
_converse
.
session
!==
undefined
)
{
...
...
@@ -548,15 +547,66 @@ function clearSession () {
}
/**
* Creates a new Strophe.Connection instance and if applicable, attempt to
* restore the BOSH session or if `auto_login` is true, attempt to log in.
async
function
onDomainDiscovered
(
response
)
{
const
text
=
await
response
.
text
();
const
xrd
=
(
new
window
.
DOMParser
()).
parseFromString
(
text
,
"
text/xml
"
).
firstElementChild
;
if
(
xrd
.
nodeName
!=
"
XRD
"
||
xrd
.
namespaceURI
!=
"
http://docs.oasis-open.org/ns/xri/xrd-1.0
"
)
{
return
_converse
.
log
(
"
Could not discover XEP-0156 connection methods
"
,
Strophe
.
LogLevel
.
WARN
);
}
const
bosh_links
=
sizzle
(
`Link[rel="urn:xmpp:alt-connections:xbosh"]`
,
xrd
);
const
ws_links
=
sizzle
(
`Link[rel="urn:xmpp:alt-connections:websocket"]`
,
xrd
);
const
bosh_methods
=
bosh_links
.
map
(
el
=>
el
.
getAttribute
(
'
href
'
));
const
ws_methods
=
ws_links
.
map
(
el
=>
el
.
getAttribute
(
'
href
'
));
// TODO: support multiple endpoints
_converse
.
websocket_url
=
ws_methods
.
pop
();
_converse
.
bosh_service_url
=
bosh_methods
.
pop
();
if
(
bosh_methods
.
length
===
0
&&
ws_methods
.
length
===
0
)
{
_converse
.
log
(
"
onDomainDiscovered: neither BOSH nor WebSocket connection methods have been specified with XEP-0156.
"
,
Strophe
.
LogLevel
.
WARN
);
}
}
/* Use XEP-0156 to check whether this host advertises websocket or BOSH connection methods.
*/
_converse
.
initConnection
=
async
function
()
{
if
(
!
_converse
.
connection
)
{
if
(
!
_converse
.
bosh_service_url
&&
!
_converse
.
websocket_url
)
{
async
function
discoverConnectionMethods
(
domain
)
{
const
options
=
{
'
mode
'
:
'
cors
'
,
'
headers
'
:
{
'
Accept
'
:
'
application/xrd+xml, text/xml
'
}
};
const
url
=
`https://
${
domain
}
/.well-known/host-meta`
;
let
response
;
try
{
response
=
await
fetch
(
url
,
options
);
}
catch
(
e
)
{
_converse
.
log
(
`Failed to discover alternative connection methods at
${
url
}
`
,
Strophe
.
LogLevel
.
ERROR
);
return
_converse
.
log
(
e
,
Strophe
.
LogLevel
.
ERROR
);
}
if
(
response
.
status
>=
200
&&
response
.
status
<
400
)
{
await
onDomainDiscovered
(
response
);
}
else
{
_converse
.
log
(
"
Could not discover XEP-0156 connection methods
"
,
Strophe
.
LogLevel
.
WARN
);
}
}
_converse
.
initConnection
=
async
function
(
domain
)
{
if
(
_converse
.
discover_connection_methods
)
{
await
discoverConnectionMethods
(
domain
);
}
if
(
!
_converse
.
bosh_service_url
)
{
if
(
_converse
.
authentication
===
_converse
.
PREBIND
)
{
throw
new
Error
(
"
authentication is set to 'prebind' but we don't have a BOSH connection
"
);
}
if
(
!
_converse
.
websocket_url
)
{
throw
new
Error
(
"
initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.
"
);
}
}
if
((
'
WebSocket
'
in
window
||
'
MozWebSocket
'
in
window
)
&&
_converse
.
websocket_url
)
{
_converse
.
connection
=
new
Strophe
.
Connection
(
_converse
.
websocket_url
,
...
...
@@ -575,10 +625,6 @@ _converse.initConnection = async function () {
throw
new
Error
(
"
initConnection: this browser does not support
"
+
"
websockets and bosh_service_url wasn't specified.
"
);
}
if
(
_converse
.
auto_login
||
_converse
.
keepalive
)
{
await
_converse
.
api
.
user
.
login
(
null
,
null
,
true
);
}
}
setUpXMLLogging
();
/**
* Triggered once the `Strophe.Connection` constructor has been initialized, which
...
...
@@ -587,10 +633,10 @@ _converse.initConnection = async function () {
* @event _converse#connectionInitialized
*/
_converse
.
api
.
trigger
(
'
connectionInitialized
'
);
}
;
}
async
function
setUserJID
(
jid
)
{
async
function
initSession
(
jid
)
{
const
bare_jid
=
Strophe
.
getBareJidFromJid
(
jid
).
toLowerCase
();
const
id
=
`converse.session-
${
bare_jid
}
`
;
if
(
!
_converse
.
session
||
_converse
.
session
.
get
(
'
id
'
)
!==
id
)
{
...
...
@@ -612,23 +658,14 @@ async function setUserJID (jid) {
}
else
{
saveJIDtoSession
(
jid
);
}
/**
* Triggered whenever the user's JID has been updated
* @event _converse#setUserJID
*/
_converse
.
api
.
trigger
(
'
setUserJID
'
);
return
jid
;
}
function
saveJIDtoSession
(
jid
)
{
jid
=
_converse
.
session
.
get
(
'
jid
'
)
||
jid
;
if
(
_converse
.
authentication
!==
_converse
.
ANONYMOUS
&&
!
Strophe
.
getResourceFromJid
(
jid
))
{
jid
=
jid
.
toLowerCase
()
+
_converse
.
generateResource
();
}
// Set JID on the connection object so that when we call
// `connection.bind` the new resource is found by Strophe.js
// and sent to the XMPP server.
_converse
.
connection
.
jid
=
jid
;
_converse
.
jid
=
jid
;
_converse
.
bare_jid
=
Strophe
.
getBareJidFromJid
(
jid
);
_converse
.
resource
=
Strophe
.
getResourceFromJid
(
jid
);
...
...
@@ -640,6 +677,37 @@ function saveJIDtoSession (jid) {
'
domain
'
:
_converse
.
domain
,
'
active
'
:
true
});
// Set JID on the connection object so that when we call `connection.bind`
// the new resource is found by Strophe.js and sent to the XMPP server.
_converse
.
connection
.
jid
=
jid
;
}
/**
* Stores the passed in JID for the current user, potentially creating a
* resource if the JID is bare.
*
* Given that we can only create an XMPP connection if we know the domain of
* the server connect to and we only know this once we know the JID, we also
* call {@link _converse.initConnection } (if necessary) to make sure that the
* connection is set up.
*
* @method _converse#setUserJID
* @emits _converse#setUserJID
* @params { String } jid
*/
_converse
.
setUserJID
=
async
function
(
jid
)
{
if
(
!
_converse
.
connection
||
!
u
.
isSameDomain
(
_converse
.
connection
.
jid
,
jid
))
{
const
domain
=
Strophe
.
getDomainFromJid
(
jid
)
await
_converse
.
initConnection
(
domain
);
}
await
initSession
(
jid
);
/**
* Triggered whenever the user's JID has been updated
* @event _converse#setUserJID
*/
_converse
.
api
.
trigger
(
'
setUserJID
'
);
return
jid
;
}
...
...
@@ -649,7 +717,7 @@ async function onConnected (reconnecting) {
*/
delete
_converse
.
connection
.
reconnecting
;
_converse
.
connection
.
flush
();
// Solves problem of returned PubSub BOSH response not received by browser
await
setUserJID
(
_converse
.
connection
.
jid
);
await
_converse
.
setUserJID
(
_converse
.
connection
.
jid
);
/**
* Synchronous event triggered after we've sent an IQ to bind the
* user's JID resource for this session.
...
...
@@ -681,9 +749,9 @@ function setUpXMLLogging () {
async
function
finishInitialization
()
{
initClientConfig
();
initPlugins
();
await
_converse
.
initConnection
();
_converse
.
registerGlobalEventHandlers
();
if
(
!
Backbone
.
history
.
started
)
{
if
(
!
Backbone
.
History
.
started
)
{
Backbone
.
history
.
start
();
}
if
(
_converse
.
idle_presence_timeout
>
0
)
{
...
...
@@ -691,6 +759,10 @@ async function finishInitialization () {
_converse
.
api
.
disco
.
own
.
features
.
add
(
Strophe
.
NS
.
IDLE
);
});
}
if
(
_converse
.
auto_login
||
_converse
.
keepalive
&&
_
.
invoke
(
_converse
.
pluggable
.
plugins
[
'
converse-bosh
'
],
'
enabled
'
))
{
await
_converse
.
api
.
user
.
login
(
null
,
null
,
true
);
}
}
...
...
@@ -706,6 +778,7 @@ function finishDisconnection () {
_converse
.
connection
.
reset
();
tearDown
();
clearSession
();
delete
_converse
.
connection
;
/**
* Triggered after converse.js has disconnected from the XMPP server.
* @event _converse#disconnected
...
...
@@ -725,7 +798,7 @@ function fetchLoginCredentials (wait=0) {
xhr
.
onload
=
()
=>
{
if
(
xhr
.
status
>=
200
&&
xhr
.
status
<
400
)
{
const
data
=
JSON
.
parse
(
xhr
.
responseText
);
setUserJID
(
data
.
jid
).
then
(()
=>
{
_converse
.
setUserJID
(
data
.
jid
).
then
(()
=>
{
resolve
({
jid
:
data
.
jid
,
password
:
data
.
password
...
...
@@ -761,7 +834,7 @@ async function getLoginCredentials () {
async
function
getLoginCredentialsFromBrowser
()
{
const
creds
=
await
navigator
.
credentials
.
get
({
'
password
'
:
true
});
if
(
creds
&&
creds
.
type
==
'
password
'
&&
u
.
isValidJID
(
creds
.
id
))
{
await
setUserJID
(
creds
.
id
);
await
_converse
.
setUserJID
(
creds
.
id
);
return
{
'
jid
'
:
creds
.
id
,
'
password
'
:
creds
.
password
};
}
}
...
...
@@ -782,18 +855,20 @@ function cleanup () {
if
(
_converse
.
chatboxviews
)
{
delete
_converse
.
chatboxviews
;
}
if
(
_converse
.
connection
)
{
_converse
.
connection
.
reset
();
}
_converse
.
stopListening
();
_converse
.
off
();
}
_converse
.
initialize
=
async
function
(
settings
,
callback
)
{
cleanup
();
settings
=
settings
!==
undefined
?
settings
:
{};
const
init_promise
=
u
.
getResolveablePromise
();
PROMISES
.
forEach
(
addPromise
);
if
(
_converse
.
connection
!==
undefined
)
{
cleanup
();
}
if
(
'
onpagehide
'
in
window
)
{
// Pagehide gets thrown in more cases than unload. Specifically it
...
...
@@ -877,7 +952,7 @@ _converse.initialize = async function (settings, callback) {
if
(
_converse
.
idle_seconds
>
0
)
{
_converse
.
idle_seconds
=
0
;
}
if
(
!
_
converse
.
connection
.
authenticated
)
{
if
(
!
_
.
get
(
_converse
.
connection
,
'
authenticated
'
)
)
{
// We can't send out any stanzas when there's no authenticated connection.
// This can happen when the connection reconnects.
return
;
...
...
@@ -901,7 +976,7 @@ _converse.initialize = async function (settings, callback) {
/* An interval handler running every second.
* Used for CSI and the auto_away and auto_xa features.
*/
if
(
!
_
converse
.
connection
.
authenticated
)
{
if
(
!
_
.
get
(
_converse
.
connection
,
'
authenticated
'
)
)
{
// We can't send out any stanzas when there's no authenticated connection.
// This can happen when the connection reconnects.
return
;
...
...
@@ -1378,7 +1453,7 @@ _converse.api = {
* @returns {boolean} Whether there is an established connection or not.
*/
connected
()
{
return
(
_converse
.
connection
&&
_converse
.
connection
.
connected
)
||
fals
e
;
return
_
.
get
(
_converse
,
'
connection
'
,
{}).
connected
&&
tru
e
;
},
/**
...
...
@@ -1417,7 +1492,7 @@ _converse.api = {
// We also call `_proto._doDisconnect` so that connection event handlers
// for the old transport are removed.
if
(
_converse
.
api
.
connection
.
isType
(
'
websocket
'
)
&&
_converse
.
bosh_service_url
)
{
await
setUserJID
(
_converse
.
bare_jid
);
await
_converse
.
setUserJID
(
_converse
.
bare_jid
);
_converse
.
connection
.
_proto
.
_doDisconnect
();
_converse
.
connection
.
_proto
=
new
Strophe
.
Bosh
(
_converse
.
connection
);
_converse
.
connection
.
service
=
_converse
.
bosh_service_url
;
...
...
@@ -1426,9 +1501,9 @@ _converse.api = {
// When reconnecting anonymously, we need to connect with only
// the domain, not the full JID that we had in our previous
// (now failed) session.
await
setUserJID
(
_converse
.
settings
.
jid
);
await
_converse
.
setUserJID
(
_converse
.
settings
.
jid
);
}
else
{
await
setUserJID
(
_converse
.
bare_jid
);
await
_converse
.
setUserJID
(
_converse
.
bare_jid
);
}
_converse
.
connection
.
_proto
.
_doDisconnect
();
_converse
.
connection
.
_proto
=
new
Strophe
.
Websocket
(
_converse
.
connection
);
...
...
@@ -1439,7 +1514,7 @@ _converse.api = {
// When reconnecting anonymously, we need to connect with only
// the domain, not the full JID that we had in our previous
// (now failed) session.
await
setUserJID
(
_converse
.
settings
.
jid
);
await
_converse
.
setUserJID
(
_converse
.
settings
.
jid
);
}
if
(
_converse
.
connection
.
reconnecting
)
{
debouncedReconnect
();
...
...
@@ -1527,20 +1602,19 @@ _converse.api = {
* fails to restore a previous auth'd session.
*/
async
login
(
jid
,
password
,
automatic
=
false
)
{
if
(
_converse
.
api
.
connection
.
isType
(
'
bosh
'
))
{
if
(
jid
||
_converse
.
jid
)
{
jid
=
await
_converse
.
setUserJID
(
jid
||
_converse
.
jid
);
}
// See whether there is a BOSH session to re-attach to
if
(
_
.
invoke
(
_converse
.
pluggable
.
plugins
[
'
converse-bosh
'
],
'
enabled
'
))
{
if
(
await
_converse
.
restoreBOSHSession
())
{
return
;
}
else
if
(
_converse
.
authentication
===
_converse
.
PREBIND
&&
(
!
automatic
||
_converse
.
auto_login
))
{
return
_converse
.
startNewPreboundBOSHSession
();
}
}
else
if
(
_converse
.
authentication
===
_converse
.
PREBIND
)
{
throw
new
Error
(
"
authentication is set to 'prebind' but we don't have a BOSH connection
"
);
}
if
(
jid
||
_converse
.
jid
)
{
// Reassign because we might have gained a resource
jid
=
await
setUserJID
(
jid
||
_converse
.
jid
);
}
password
=
password
||
_converse
.
password
;
const
credentials
=
(
jid
&&
password
)
?
{
jid
,
password
}
:
null
;
attemptNonPreboundSession
(
credentials
,
automatic
);
...
...
@@ -1866,6 +1940,11 @@ _converse.api = {
* _converse.api.send(msg);
*/
send
(
stanza
)
{
if
(
!
_converse
.
api
.
connection
.
connected
())
{
_converse
.
log
(
"
Not sending stanza because we're not connected!
"
,
Strophe
.
LogLevel
.
WARN
);
_converse
.
log
(
Strophe
.
serialize
(
stanza
),
Strophe
.
LogLevel
.
WARN
);
return
;
}
if
(
_
.
isString
(
stanza
))
{
stanza
=
u
.
toStanza
(
stanza
);
}
...
...
src/headless/converse-muc.js
View file @
9d77a4ef
...
...
@@ -633,7 +633,7 @@ converse.plugins.add('converse-muc', {
disco_entity
.
destroy
();
}
}
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
this
.
sendUnavailablePresence
(
exit_msg
);
}
u
.
safeSave
(
this
,
{
'
connection_status
'
:
converse
.
ROOMSTATUS
.
DISCONNECTED
});
...
...
src/headless/utils/core.js
View file @
9d77a4ef
...
...
@@ -107,6 +107,15 @@ u.isSameBareJID = function (jid1, jid2) {
Strophe
.
getBareJidFromJid
(
jid2
).
toLowerCase
();
};
u
.
isSameDomain
=
function
(
jid1
,
jid2
)
{
if
(
!
_
.
isString
(
jid1
)
||
!
_
.
isString
(
jid2
))
{
return
false
;
}
return
Strophe
.
getDomainFromJid
(
jid1
).
toLowerCase
()
===
Strophe
.
getDomainFromJid
(
jid2
).
toLowerCase
();
};
u
.
isNewMessage
=
function
(
message
)
{
/* Given a stanza, determine whether it's a new
* message, i.e. not a MAM archived one.
...
...
tests/mock.js
View file @
9d77a4ef
...
...
@@ -9,7 +9,6 @@
const
Strophe
=
converse
.
env
.
Strophe
;
const
dayjs
=
converse
.
env
.
dayjs
;
const
$iq
=
converse
.
env
.
$iq
;
const
u
=
converse
.
env
.
utils
;
window
.
libsignal
=
{
'
SignalProtocolAddress
'
:
function
(
name
,
device_id
)
{
...
...
@@ -32,7 +31,7 @@
return
Promise
.
resolve
(
key_and_tag
);
}
},
'
SessionBuilder
'
:
function
(
storage
,
remote_address
)
{
'
SessionBuilder
'
:
function
(
storage
,
remote_address
)
{
// eslint-disable-line no-unused-vars
this
.
processPreKey
=
function
()
{
return
Promise
.
resolve
();
}
...
...
@@ -116,15 +115,18 @@
'
preventDefault
'
:
function
()
{}
};
mock
.
mock_connection
=
function
()
{
// eslint-disable-line wrap-iife
return
function
()
{
const
OriginalConnection
=
Strophe
.
Connection
;
function
MockConnection
(
service
,
options
)
{
OriginalConnection
.
call
(
this
,
service
,
options
);
Strophe
.
Bosh
.
prototype
.
_processRequest
=
function
()
{};
// Don't attempt to send out stanzas
const
c
=
new
Strophe
.
Connection
(
'
jasmine tests
'
);
const
sendIQ
=
c
.
sendIQ
;
const
sendIQ
=
this
.
sendIQ
;
c
.
IQ_stanzas
=
[];
c
.
IQ_ids
=
[];
c
.
sendIQ
=
function
(
iq
,
callback
,
errback
)
{
this
.
IQ_stanzas
=
[];
this
.
IQ_ids
=
[];
this
.
sendIQ
=
function
(
iq
,
callback
,
errback
)
{
if
(
!
_
.
isElement
(
iq
))
{
iq
=
iq
.
nodeTree
;
}
...
...
@@ -134,9 +136,9 @@
return
id
;
}
const
send
=
c
.
send
;
c
.
sent_stanzas
=
[];
c
.
send
=
function
(
stanza
)
{
const
send
=
this
.
send
;
this
.
sent_stanzas
=
[];
this
.
send
=
function
(
stanza
)
{
if
(
_
.
isElement
(
stanza
))
{
this
.
sent_stanzas
.
push
(
stanza
);
}
else
{
...
...
@@ -145,11 +147,11 @@
return
send
.
apply
(
this
,
arguments
);
}
c
.
features
=
Strophe
.
xmlHtmlNode
(
this
.
features
=
Strophe
.
xmlHtmlNode
(
'
<stream:features xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">
'
+
'
<ver xmlns="urn:xmpp:features:rosterver"/>
'
+
'
<csi xmlns="urn:xmpp:csi:0"/>
'
+
'
<c
xmlns="http://jabber.org/protocol/caps" ver="UwBpfJpEt3IoLYfWma/o/p3FFRo=" hash="sha-1" node="http://prosody.im"/>
'
+
'
<this
xmlns="http://jabber.org/protocol/caps" ver="UwBpfJpEt3IoLYfWma/o/p3FFRo=" hash="sha-1" node="http://prosody.im"/>
'
+
'
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
'
+
'
<required/>
'
+
'
</bind>
'
+
...
...
@@ -159,52 +161,41 @@
'
</session>
'
+
'
</stream:features>
'
).
firstChild
;
c
.
_proto
.
_connect
=
function
()
{
c
.
connected
=
true
;
c
.
mock
=
true
;
c
.
jid
=
'
romeo@montague.lit/orchard
'
;
c
.
_changeConnectStatus
(
Strophe
.
Status
.
BINDREQUIRED
);
this
.
_proto
.
_connect
=
()
=>
{
this
.
connected
=
true
;
this
.
mock
=
true
;
this
.
jid
=
'
romeo@montague.lit/orchard
'
;
this
.
_changeConnectStatus
(
Strophe
.
Status
.
BINDREQUIRED
);
};
c
.
bind
=
function
()
{
c
.
authenticated
=
true
;
this
.
bind
=
()
=>
{
this
.
authenticated
=
true
;
c
.
_changeConnectStatus
(
Strophe
.
Status
.
CONNECTED
);
this
.
authenticated
=
true
;
this
.
_changeConnectStatus
(
Strophe
.
Status
.
CONNECTED
);
};
c
.
_proto
.
_disconnect
=
function
()
{
c
.
_onDisconnectTimeout
()
;
this
.
_proto
.
_disconnect
=
()
=>
this
.
_onDisconnectTimeout
();
this
.
_proto
.
_onDisconnectTimeout
=
_
.
noop
;
}
c
.
_proto
.
_onDisconnectTimeout
=
_
.
noop
;
return
c
;
};
}();
MockConnection
.
prototype
=
Object
.
create
(
OriginalConnection
.
prototype
);
Strophe
.
Connection
=
MockConnection
;
async
function
initConverse
(
settings
,
spies
=
{}
,
promises
)
{
async
function
initConverse
(
settings
,
spies
=
{})
{
window
.
localStorage
.
clear
();
window
.
sessionStorage
.
clear
();
const
el
=
document
.
querySelector
(
'
#conversejs
'
);
if
(
el
)
{
el
.
parentElement
.
removeChild
(
el
);
}
const
connection
=
mock
.
mock_connection
();
if
(
spies
&&
spies
.
connection
)
{
spies
.
connection
.
forEach
(
method
=>
spyOn
(
connection
,
method
));
}
const
_converse
=
await
converse
.
initialize
(
Object
.
assign
({
'
i18n
'
:
'
en
'
,
'
animate
'
:
false
,
'
auto_subscribe
'
:
false
,
'
play_sounds
'
:
false
,
'
bosh_service_url
'
:
'
montague.lit/http-bind
'
,
'
connection
'
:
connection
,
'
animate
'
:
false
,
'
use_emojione
'
:
false
,
'
debug
'
:
false
,
'
i18n
'
:
'
en
'
,
'
no_trimming
'
:
true
,
'
play_sounds
'
:
false
,
'
use_emojione
'
:
false
,
'
view_mode
'
:
mock
.
view_mode
,
'
debug
'
:
false
},
settings
||
{}));
if
(
spies
&&
spies
.
_converse
)
{
...
...
@@ -214,7 +205,7 @@
_converse
.
ChatBoxViews
.
prototype
.
trimChat
=
function
()
{};
_converse
.
api
.
vcard
.
get
=
function
(
model
,
force
)
{
return
new
Promise
(
(
resolve
,
reject
)
=>
{
return
new
Promise
(
resolve
=>
{
let
jid
;
if
(
_
.
isString
(
model
))
{
jid
=
model
;
...
...
@@ -263,9 +254,13 @@
return
async
done
=>
{
const
_converse
=
await
initConverse
(
settings
,
spies
);
async
function
_done
()
{
if
(
_converse
.
api
.
connection
.
connected
())
{
await
_converse
.
api
.
user
.
logout
();
}
const
el
=
document
.
querySelector
(
'
#conversejs
'
);
if
(
el
)
{
el
.
parentElement
.
removeChild
(
el
);
}
done
();
}
await
Promise
.
all
((
promise_names
||
[]).
map
(
_converse
.
api
.
waitUntil
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment