Bug 954193 - reorganize purplexpcom, part 2: rewrite the core service, account list, status handling and protocol plugin loading in JS components that don't depend on libpurple.
--HG-- rename : purple/purplexpcom/public/purpleIProtocol.idl => chat/components/public/prplIProtocol.idl
This commit is contained in:
Родитель
b42adbfac2
Коммит
a53db18a77
|
@ -45,9 +45,14 @@ MODULE = chat
|
|||
|
||||
XPIDLSRCS = \
|
||||
ibILogger.idl \
|
||||
imIAccount.idl \
|
||||
imIAccountsService.idl \
|
||||
imICommandsService.idl \
|
||||
imIContactsService.idl \
|
||||
imIConversationsService.idl \
|
||||
imICoreService.idl \
|
||||
imIUserStatusInfo.idl \
|
||||
prplIProtocol.idl \
|
||||
purpleIConversation.idl \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include "nsISupports.idl"
|
||||
#include "nsISimpleEnumerator.idl"
|
||||
|
||||
interface purpleIAccount;
|
||||
interface imIAccount;
|
||||
interface imIAccountBuddy;
|
||||
interface imIBuddy;
|
||||
interface imIContact;
|
||||
|
@ -56,5 +56,5 @@ interface ibILogger: nsISupports {
|
|||
nsISimpleEnumerator getLogsForBuddy(in imIBuddy aBuddy);
|
||||
nsISimpleEnumerator getLogsForContact(in imIContact aContact);
|
||||
nsISimpleEnumerator getLogsForConversation(in purpleIConversation aConversation);
|
||||
nsISimpleEnumerator getSystemLogsForAccount(in purpleIAccount aAccount);
|
||||
nsISimpleEnumerator getSystemLogsForAccount(in imIAccount aAccount);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Instantbird messenging client, released
|
||||
* 2007.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Florian QUEZE <florian@instantbird.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "purpleIConversation.idl"
|
||||
#include "purpleIProxy.idl"
|
||||
#include "imIUserStatusInfo.idl"
|
||||
|
||||
interface imITag;
|
||||
interface imIBuddy;
|
||||
interface imIAccountBuddy;
|
||||
interface imIAccount;
|
||||
interface prplIProtocol;
|
||||
|
||||
/*
|
||||
* Used to join chat rooms.
|
||||
*/
|
||||
|
||||
[ptr] native GHashTablePtr(GHashTable);
|
||||
|
||||
[scriptable, uuid(ea7ab156-d25e-46cc-93ef-29f77b3c0795)]
|
||||
interface purpleIChatRoomFieldValues: nsISupports {
|
||||
AUTF8String getValue(in AUTF8String aIdentifier);
|
||||
void setValue(in AUTF8String aIdentifier, in AUTF8String aValue);
|
||||
|
||||
[noscript] readonly attribute GHashTablePtr hashTable;
|
||||
};
|
||||
|
||||
[scriptable, uuid(19dff981-b125-4a70-bc1a-efc783d07137)]
|
||||
interface purpleIChatRoomField: nsISupports {
|
||||
readonly attribute AUTF8String label;
|
||||
readonly attribute AUTF8String identifier;
|
||||
readonly attribute boolean required;
|
||||
|
||||
const short TYPE_TEXT = 0;
|
||||
const short TYPE_PASSWORD = 1;
|
||||
const short TYPE_INT = 2;
|
||||
|
||||
readonly attribute short type;
|
||||
readonly attribute long min;
|
||||
readonly attribute long max;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This interface should be implemented by the protocol plugin.
|
||||
*/
|
||||
[scriptable, uuid(fb1b29cb-63ba-4335-9f44-63aea3f616a3)]
|
||||
interface prplIAccount: nsISupports {
|
||||
readonly attribute imIAccount imAccount;
|
||||
|
||||
// observe should only be called by the imIAccount
|
||||
// implementation to report user status changes that affect this account.
|
||||
void observe(in nsISupports aObj, in string aEvent,
|
||||
[optional] in wstring aData);
|
||||
|
||||
/* Uninitialize the prplIAccount instance. This is typically done
|
||||
automatically at shutdown (by the core service) or as part of
|
||||
the 'remove' method. */
|
||||
void unInit();
|
||||
|
||||
void connect();
|
||||
void disconnect();
|
||||
|
||||
purpleIConversation createConversation(in AUTF8String aName);
|
||||
|
||||
// Used when the user wants to add a buddy to the buddy list
|
||||
void addBuddy(in imITag aTag, in AUTF8String aName);
|
||||
|
||||
// Used while loading the buddy list at startup.
|
||||
imIAccountBuddy loadBuddy(in imIBuddy aBuddy, in imITag aTag);
|
||||
|
||||
/* Request more info on a buddy (typically a chat buddy).
|
||||
* The result (if any) will be provided by a user-info-received
|
||||
* notification dispatched through the observer service:
|
||||
* - aSubject will be an nsISimpleEnumerator of purpleITooltipInfo,
|
||||
* Do NOT store aSubject. Use it right away. The memory it points to
|
||||
* will be freed right after the notification is dispatched.
|
||||
* - aData will be aBuddyName.
|
||||
*/
|
||||
void requestBuddyInfo(in AUTF8String aBuddyName);
|
||||
|
||||
readonly attribute boolean canJoinChat;
|
||||
nsISimpleEnumerator getChatRoomFields();
|
||||
purpleIChatRoomFieldValues getChatRoomDefaultFieldValues([optional] in AUTF8String aDefaultChatName);
|
||||
/*
|
||||
* Create a new chat conversation if it doesn't already exist.
|
||||
*/
|
||||
void joinChat(in purpleIChatRoomFieldValues aComponents);
|
||||
|
||||
readonly attribute AUTF8String normalizedName;
|
||||
|
||||
attribute purpleIProxyInfo proxyInfo;
|
||||
|
||||
// protocol specific options: those functions set the protocol
|
||||
// specific options for the PurpleAccount
|
||||
void setBool(in string aName, in boolean aVal);
|
||||
void setInt(in string aName, in long aVal);
|
||||
void setString(in string aName, in string aVal);
|
||||
|
||||
/* When a connection error occurred, this value indicates the type of error */
|
||||
readonly attribute short connectionErrorReason;
|
||||
|
||||
/* Possible connection error reasons:
|
||||
ERROR_NETWORK_ERROR and ERROR_ENCRYPTION_ERROR are not fatal and
|
||||
should enable the automatic reconnection feature. */
|
||||
const short NO_ERROR = -1;
|
||||
const short ERROR_NETWORK_ERROR = 0;
|
||||
const short ERROR_INVALID_USERNAME = 1;
|
||||
const short ERROR_AUTHENTICATION_FAILED = 2;
|
||||
const short ERROR_AUTHENTICATION_IMPOSSIBLE = 3;
|
||||
const short ERROR_NO_SSL_SUPPORT = 4;
|
||||
const short ERROR_ENCRYPTION_ERROR = 5;
|
||||
const short ERROR_NAME_IN_USE = 6;
|
||||
const short ERROR_INVALID_SETTINGS = 7;
|
||||
const short ERROR_CERT_NOT_PROVIDED = 8;
|
||||
const short ERROR_CERT_UNTRUSTED = 9;
|
||||
const short ERROR_CERT_EXPIRED = 10;
|
||||
const short ERROR_CERT_NOT_ACTIVATED = 11;
|
||||
const short ERROR_CERT_HOSTNAME_MISMATCH = 12;
|
||||
const short ERROR_CERT_FINGERPRINT_MISMATCH = 13;
|
||||
const short ERROR_CERT_SELF_SIGNED = 14;
|
||||
const short ERROR_CERT_OTHER_ERROR = 15;
|
||||
const short ERROR_OTHER_ERROR = 16;
|
||||
|
||||
/* From PurpleConnectionFlags */
|
||||
|
||||
// PURPLE_CONNECTION_HTML
|
||||
// Connection sends/receives in 'HTML'.
|
||||
readonly attribute boolean HTMLEnabled;
|
||||
|
||||
// PURPLE_CONNECTION_NO_BGCOLOR
|
||||
// Connection does not send/receive background colors.
|
||||
readonly attribute boolean noBackgroundColors;
|
||||
|
||||
// PURPLE_CONNECTION_AUTO_RESP
|
||||
// Send auto responses when away.
|
||||
readonly attribute boolean autoResponses;
|
||||
|
||||
// PURPLE_CONNECTION_FORMATTING_WBFO
|
||||
// The text buffer must be formatted as a whole.
|
||||
readonly attribute boolean singleFormatting;
|
||||
|
||||
// PURPLE_CONNECTION_NO_NEWLINES
|
||||
// No new lines are allowed in outgoing messages.
|
||||
readonly attribute boolean noNewlines;
|
||||
|
||||
// PURPLE_CONNECTION_NO_FONTSIZE
|
||||
// Connection does not send/receive font sizes.
|
||||
readonly attribute boolean noFontSizes;
|
||||
|
||||
// PURPLE_CONNECTION_NO_URLDESC
|
||||
// Connection does not support descriptions with links.
|
||||
readonly attribute boolean noUrlDesc;
|
||||
|
||||
// PURPLE_CONNECTION_NO_IMAGES
|
||||
// Connection does not support sending of images.
|
||||
readonly attribute boolean noImages;
|
||||
|
||||
// This is currently used only by Twitter.
|
||||
readonly attribute PRInt32 maxMessageLength;
|
||||
};
|
||||
|
||||
/* This interface should be implemented by the im core. It inherits
|
||||
from prplIAccount and in most cases will forward the calls for the
|
||||
inherited members to a prplIAccount account instance implemented by
|
||||
the protocol plugin. */
|
||||
[scriptable, uuid(20a85b44-e220-4f23-85bf-f8523d1a2b08)]
|
||||
interface imIAccount: prplIAccount {
|
||||
/* Check if autologin is enabled for this account, connect it now. */
|
||||
void checkAutoLogin();
|
||||
|
||||
/* Delete the account (from the preferences, mozStorage, and call unInit). */
|
||||
void remove();
|
||||
|
||||
/* Cancel the timer that automatically reconnects the account that were
|
||||
disconnected with a non fatal error */
|
||||
void cancelReconnection();
|
||||
|
||||
readonly attribute AUTF8String name;
|
||||
readonly attribute AUTF8String id;
|
||||
readonly attribute PRUint32 numericId;
|
||||
readonly attribute prplIProtocol protocol;
|
||||
readonly attribute prplIAccount prplAccount;
|
||||
|
||||
// Save account specific preferences to disk.
|
||||
void save();
|
||||
|
||||
attribute boolean autoLogin;
|
||||
|
||||
/* This is the value when the preference firstConnectionState is not set.
|
||||
It indicates that the account has already been successfully connected at
|
||||
least once with the current parameters. */
|
||||
const short FIRST_CONNECTION_OK = 0;
|
||||
/* Set when the account has never had a successful connection
|
||||
with the current parameters */
|
||||
const short FIRST_CONNECTION_UNKNOWN = 1;
|
||||
/* Set when the account is trying to connect for the first time
|
||||
with the current parameters (removed after a successsful connection) */
|
||||
const short FIRST_CONNECTION_PENDING = 2;
|
||||
/* Set at startup when the previous state was pending */
|
||||
const short FIRST_CONNECTION_CRASHED = 4;
|
||||
|
||||
attribute short firstConnectionState;
|
||||
|
||||
// FIXME password should be in password manager
|
||||
attribute AUTF8String password;
|
||||
|
||||
attribute AUTF8String alias;
|
||||
|
||||
/* While an account is connecting, this attribute contains a message
|
||||
indicating the current step of the connection */
|
||||
readonly attribute AUTF8String connectionStateMsg;
|
||||
|
||||
/* Number of the reconnection attempt
|
||||
* 0 means that no automatic reconnection currently pending
|
||||
* n means the nth reconnection attempt is pending
|
||||
*/
|
||||
readonly attribute PRUint16 reconnectAttempt;
|
||||
|
||||
/* Time stamp of the next reconnection attempt */
|
||||
readonly attribute PRInt64 timeOfNextReconnect;
|
||||
|
||||
/* Time stamp of the last connection (value not reliable if not connected) */
|
||||
readonly attribute PRInt64 timeOfLastConnect;
|
||||
|
||||
/* Additional possible connection error reasons:
|
||||
* (Use a big enough number that it can't conflict with error
|
||||
* codes used in prplIAccount).
|
||||
*/
|
||||
const short ERROR_UNKNOWN_PRPL = 42;
|
||||
const short ERROR_CRASHED = 43;
|
||||
const short ERROR_MISSING_PASSWORD = 44;
|
||||
|
||||
/* A message describing the connection error */
|
||||
readonly attribute AUTF8String connectionErrorMessage;
|
||||
|
||||
/* Info about the connection state and flags */
|
||||
const short STATE_DISCONNECTED = 0;
|
||||
const short STATE_CONNECTED = 1;
|
||||
const short STATE_CONNECTING = 2;
|
||||
const short STATE_DISCONNECTING = 3;
|
||||
|
||||
readonly attribute short connectionState;
|
||||
|
||||
/* The following 4 properties use the above connectionState value. */
|
||||
readonly attribute boolean disconnected;
|
||||
readonly attribute boolean connected;
|
||||
readonly attribute boolean connecting;
|
||||
readonly attribute boolean disconnecting;
|
||||
|
||||
/* The imIUserStatusInfo instance this account should observe for
|
||||
status changes. When this is null (the default value), the
|
||||
account will observe the global status. */
|
||||
attribute imIUserStatusInfo observedStatusInfo;
|
||||
// Same as above, but never null (it fallbacks to the global status info).
|
||||
attribute imIUserStatusInfo statusInfo;
|
||||
|
||||
// imIAccount also implements an observe method but this
|
||||
// observe should only be called by the prplIAccount
|
||||
// implementations to report connection status changes.
|
||||
};
|
|
@ -0,0 +1,97 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Instantbird messenging client, released
|
||||
* 2007.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Florian QUEZE <florian@instantbird.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsISimpleEnumerator.idl"
|
||||
#include "imIAccount.idl"
|
||||
|
||||
[scriptable, uuid(b3b6459a-5c26-47b8-8e9c-ba838b6f632a)]
|
||||
interface imIAccountsService: nsISupports {
|
||||
void initAccounts();
|
||||
void unInitAccounts();
|
||||
|
||||
/* This attribute is set to AUTOLOGIN_ENABLED by default. It can be set to
|
||||
any other value before the initialization of this service to prevent
|
||||
accounts with autoLogin enabled from being connected when libpurple is
|
||||
initialized.
|
||||
Any value other than the ones listed below will disable autoLogin and
|
||||
display a generic message in the Account Manager. */
|
||||
attribute short autoLoginStatus;
|
||||
|
||||
const short AUTOLOGIN_ENABLED = 0;
|
||||
const short AUTOLOGIN_USER_DISABLED = 1;
|
||||
const short AUTOLOGIN_SAFE_MODE = 2;
|
||||
const short AUTOLOGIN_CRASH = 3;
|
||||
const short AUTOLOGIN_START_OFFLINE = 4;
|
||||
|
||||
/* The method should be used to connect all accounts with autoLogin enabled.
|
||||
Some use cases:
|
||||
- if the autologin was disabled at startup
|
||||
- after a loss of internet connectivity that disconnected all accounts.
|
||||
*/
|
||||
void processAutoLogin();
|
||||
|
||||
imIAccount getAccountById(in AUTF8String aAccountId);
|
||||
|
||||
/* will throw NS_ERROR_FAILURE if not found */
|
||||
imIAccount getAccountByNumericId(in PRUint32 aAccountId);
|
||||
|
||||
nsISimpleEnumerator getAccounts();
|
||||
|
||||
/* will fire the event account-added */
|
||||
imIAccount createAccount(in AUTF8String aName, in AUTF8String aPrpl);
|
||||
|
||||
/* will fire the event account-removed */
|
||||
void deleteAccount(in AUTF8String aAccountId);
|
||||
};
|
||||
|
||||
/*
|
||||
account related notifications sent to nsIObserverService:
|
||||
- account-added: a new account has been created
|
||||
- account-removed: the account has been deleted
|
||||
- account-connecting: the account is being connected
|
||||
- account-connected: the account is now connected
|
||||
- account-connect-error: the account is disconnect with an error.
|
||||
(before account-disconnecting)
|
||||
- account-disconnecting: the account is being disconnected
|
||||
- account-disconnected: the account is now disconnected
|
||||
- account-updated: when some settings have changed
|
||||
- account-list-updated: when the list of account is reordered.
|
||||
These events can be watched using an nsIObserver.
|
||||
The associated imIAccount will be given as a parameter
|
||||
(except for account-list-updated).
|
||||
*/
|
|
@ -44,7 +44,8 @@ interface imITag;
|
|||
interface imIContact;
|
||||
interface imIBuddy;
|
||||
interface imIAccountBuddy;
|
||||
interface purpleIProtocol;
|
||||
interface imIAccount;
|
||||
interface prplIProtocol;
|
||||
|
||||
[scriptable, uuid(f1619b49-310b-47aa-ab1c-238aba084c62)]
|
||||
interface imIContactsService: nsISupports {
|
||||
|
@ -54,7 +55,7 @@ interface imIContactsService: nsISupports {
|
|||
imIContact getContactById(in long aId);
|
||||
imIBuddy getBuddyById(in long aId);
|
||||
imIBuddy getBuddyByNameAndProtocol(in AUTF8String aNormalizedName,
|
||||
in purpleIProtocol aPrpl);
|
||||
in prplIProtocol aPrpl);
|
||||
|
||||
// These 3 functions are called by the protocol plugins when
|
||||
// synchronizing the buddy list with the server stored list,
|
||||
|
@ -63,6 +64,22 @@ interface imIContactsService: nsISupports {
|
|||
void accountBuddyRemoved(in imIAccountBuddy aAccountBuddy);
|
||||
void accountBuddyMoved(in imIAccountBuddy aAccountBuddy,
|
||||
in imITag aOldTag, in imITag aNewTag);
|
||||
|
||||
// These methods are called by the imIAccountsService implementation
|
||||
// to keep the accounts table in sync with accounts stored in the
|
||||
// preferences.
|
||||
|
||||
// Called when an account is created or loaded to store the new
|
||||
// account or ensure it doesn't conflict with an existing account
|
||||
// (to detect database corruption).
|
||||
// Will throw if a stored account has the id aId but a different
|
||||
// username or prplId.
|
||||
void storeAccount(in PRUint32 aId, in AUTF8String aUserName,
|
||||
in AUTF8String aPrplId);
|
||||
// Check if an account id already exists in the database.
|
||||
boolean accountIdExists(in PRUint32 aId);
|
||||
// Called when deleting an account to remove it from blist.sqlite.
|
||||
void forgetAccount(in PRUint32 aId);
|
||||
};
|
||||
|
||||
[scriptable, uuid(f799a9c2-23f2-4fd1-96fb-515bad238f8c)]
|
||||
|
@ -255,7 +272,7 @@ interface imIContact: imIStatusInfo {
|
|||
[scriptable, uuid(fea582a0-3839-4d80-bcab-0ff82ae8f97f)]
|
||||
interface imIBuddy: imIStatusInfo {
|
||||
readonly attribute long id;
|
||||
readonly attribute purpleIProtocol protocol;
|
||||
readonly attribute prplIProtocol protocol;
|
||||
readonly attribute AUTF8String userName; // may be formatted
|
||||
readonly attribute AUTF8String normalizedName; // normalized userName
|
||||
// The optional server alias is in displayName (inherited from imIStatusInfo)
|
||||
|
@ -330,7 +347,7 @@ interface imIAccountBuddy: imIStatusInfo {
|
|||
// Contacts service when accountBuddyAdded is called on this
|
||||
// instance of imIAccountBuddy.
|
||||
attribute imIBuddy buddy;
|
||||
readonly attribute purpleIAccount account;
|
||||
readonly attribute imIAccount account;
|
||||
// Setting the tag will move the buddy to a different group on the
|
||||
// server-stored buddy list.
|
||||
attribute imITag tag;
|
||||
|
|
|
@ -93,6 +93,6 @@ interface imIConversationsService: nsISupports {
|
|||
nsISimpleEnumerator getConversations();
|
||||
purpleIConversation getConversationById(in unsigned long aId);
|
||||
purpleIConversation getConversationByNameAndAccount(in AUTF8String aName,
|
||||
in purpleIAccount aAccount,
|
||||
in imIAccount aAccount,
|
||||
in boolean aIsChat);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Instantbird messenging client, released
|
||||
* 2007.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Florian QUEZE <florian@instantbird.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "imIUserStatusInfo.idl"
|
||||
#include "nsISimpleEnumerator.idl"
|
||||
#include "prplIProtocol.idl"
|
||||
|
||||
[scriptable, uuid(205d4b2b-1ccf-4879-9ef1-f08942566151)]
|
||||
interface imICoreService: nsISupports {
|
||||
void init();
|
||||
void quit(); // will emit a prpl-quit notification.
|
||||
|
||||
// returns an enumerator on a pplIProtocol array
|
||||
nsISimpleEnumerator getProtocols();
|
||||
|
||||
prplIProtocol getProtocolById(in AUTF8String aProtocolId);
|
||||
|
||||
readonly attribute imIUserStatusInfo globalUserStatus;
|
||||
};
|
|
@ -0,0 +1,76 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Instantbird messenging client, released
|
||||
* 2010.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Florian QUEZE <florian@instantbird.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIObserver.idl"
|
||||
|
||||
//forward declarations
|
||||
interface nsILocalFile;
|
||||
interface nsIFileURL;
|
||||
|
||||
[scriptable, uuid(817918fa-1f4b-4254-9cdb-f906da91c45d)]
|
||||
interface imIUserStatusInfo: nsISupports {
|
||||
|
||||
readonly attribute AUTF8String statusText;
|
||||
|
||||
// See imIStatusInfo in imIContactsService.idl for the values.
|
||||
readonly attribute short statusType;
|
||||
|
||||
// Only works with STATUS_OFFLINE, STATUS_UNAVAILABLE, STATUS_AWAY,
|
||||
// STATUS_AVAILABLE and STATUS_INVISIBLE.
|
||||
// - When called with the status type STATUS_UNSET, only the status
|
||||
// message will be changed.
|
||||
// - When called with STATUS_OFFLINE, the aMessage parameter is ignored.
|
||||
void setStatus(in short aStatus, in AUTF8String aMessage);
|
||||
|
||||
/* Will fire an user-icon-changed notificaton. */
|
||||
void setUserIcon(in nsILocalFile aIconFile);
|
||||
|
||||
nsIFileURL getUserIcon();
|
||||
|
||||
/* The setter will fire an user-display-name-changed notificaton. */
|
||||
attribute AUTF8String displayName;
|
||||
|
||||
void addObserver(in nsIObserver aObserver);
|
||||
void removeObserver(in nsIObserver aObserver);
|
||||
/* Observers will receive the following notifications:
|
||||
* status-changed (when either the status type or text has changed)
|
||||
* user-icon-changed
|
||||
* user-display-name-changed
|
||||
* idle-time-changed
|
||||
*/
|
||||
};
|
|
@ -37,22 +37,15 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsISimpleEnumerator.idl"
|
||||
#include "imIAccount.idl"
|
||||
|
||||
/*
|
||||
* This is the libpurple protocol
|
||||
*/
|
||||
[scriptable, uuid(7d302db0-3813-4c51-8372-c7eb5fc9f3d3)]
|
||||
interface prplIProtocol: nsISupports {
|
||||
// aId is the prpl id, this method is used so that classes
|
||||
// implementing several protocol plugins can know which protocol is
|
||||
// desired for this instance.
|
||||
void init(in AUTF8String aId);
|
||||
|
||||
%{C++
|
||||
#pragma GCC visibility push(default)
|
||||
#include <libpurple/prpl.h>
|
||||
#pragma GCC visibility pop
|
||||
%}
|
||||
|
||||
[ptr] native PurpleNativePluginProtocolInfo(PurplePluginProtocolInfo);
|
||||
interface purpleIAccount;
|
||||
|
||||
[scriptable, uuid(0a51b511-4ce7-4f4c-a109-43023b72fc5a)]
|
||||
interface purpleIProtocol: nsISupports {
|
||||
readonly attribute AUTF8String name;
|
||||
readonly attribute AUTF8String id;
|
||||
readonly attribute AUTF8String normalizedName;
|
||||
|
@ -123,9 +116,9 @@ interface purpleIProtocol: nsISupports {
|
|||
// account, or uses the Mozilla proxy settings for all accounts.
|
||||
readonly attribute boolean usePurpleProxy;
|
||||
|
||||
// The key is the unique identifier needed to get account data
|
||||
// stored in the preferences.
|
||||
purpleIAccount getAccount(in AUTF8String aKey, in AUTF8String aName);
|
||||
// Get the protocol specific part of an already initialized
|
||||
// imIAccount instance.
|
||||
prplIAccount getAccount(in imIAccount aImAccount);
|
||||
};
|
||||
|
||||
[scriptable, uuid(20c4971a-f7c2-4781-8e85-69fee7b83a3d)]
|
||||
|
@ -138,7 +131,3 @@ interface purpleIUsernameSplit: nsISupports {
|
|||
the end of the string, PR_FALSE otherwise. */
|
||||
readonly attribute PRBool reverse;
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define JS_PROTOCOL_PLUGIN_CATEGORY "js-protocol-plugin"
|
||||
%}
|
|
@ -41,7 +41,7 @@
|
|||
#include "nsIObserver.idl"
|
||||
|
||||
interface imIAccountBuddy;
|
||||
interface purpleIAccount;
|
||||
interface imIAccount;
|
||||
interface nsIURI;
|
||||
interface nsIDOMDocument;
|
||||
|
||||
|
@ -56,7 +56,7 @@ interface purpleIConversation: nsISupports {
|
|||
readonly attribute boolean isChat;
|
||||
|
||||
/* The account used for this conversation */
|
||||
readonly attribute purpleIAccount account;
|
||||
readonly attribute imIAccount account;
|
||||
|
||||
/* The name of the conversation, typically in English */
|
||||
readonly attribute AUTF8String name;
|
||||
|
|
|
@ -42,14 +42,17 @@ VPATH = @srcdir@
|
|||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
imAccounts.manifest \
|
||||
imCommands.js imCommands.manifest \
|
||||
imContacts.js imContacts.manifest \
|
||||
imConversations.js imConversations.manifest \
|
||||
imCommands.js imCommands.manifest \
|
||||
imCore.js imCore.manifest \
|
||||
logger.manifest \
|
||||
smileProtocolHandler.js smileProtocolHandler.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
imAccounts.js \
|
||||
logger.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,741 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Instantbird messenging client, released
|
||||
* 2011.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Florian QUEZE <florian@instantbird.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Romain Bezut <romain@bezut.info>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
Cu.import("resource:///modules/imXPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/imServices.jsm");
|
||||
|
||||
const kPrefAutologinPending = "messenger.accounts.autoLoginPending";
|
||||
const kPrefMessengerAccounts = "messenger.accounts";
|
||||
const kPrefAccountPrefix = "messenger.account.";
|
||||
const kAccountKeyPrefix = "account";
|
||||
const kAccountOptionPrefPrefix = "options.";
|
||||
const kPrefAccountName = "name";
|
||||
const kPrefAccountPrpl = "prpl";
|
||||
const kPrefAccountPassword = "password";
|
||||
const kPrefAccountAutoLogin = "autoLogin";
|
||||
const kPrefAccountAlias = "alias";
|
||||
const kPrefAccountFirstConnectionState = "firstConnectionState";
|
||||
|
||||
var SavePrefTimer = {
|
||||
saveNow: function() {
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
this._timer = null;
|
||||
}
|
||||
Services.prefs.savePrefFile(null);
|
||||
},
|
||||
_timer: null,
|
||||
unInitTimer: function() {
|
||||
if (this._timer)
|
||||
this.saveNow();
|
||||
},
|
||||
initTimer: function() {
|
||||
if (!this._timer)
|
||||
this._timer = setTimeout(this.saveNow.bind(this), 5000);
|
||||
}
|
||||
};
|
||||
|
||||
var AutoLoginCounter = {
|
||||
_count: 0,
|
||||
startAutoLogin: function() {
|
||||
++this._count;
|
||||
if (this._count != 1)
|
||||
return;
|
||||
Services.prefs.setIntPref(kPrefAutologinPending, Date.now() / 1000);
|
||||
SavePrefTimer.saveNow();
|
||||
},
|
||||
finishedAutoLogin: function() {
|
||||
--this._count;
|
||||
if (this._count != 0)
|
||||
return;
|
||||
Services.prefs.deleteBranch(kPrefAutologinPending);
|
||||
SavePrefTimer.initTimer();
|
||||
}
|
||||
};
|
||||
|
||||
function UnknownProtocol(aPrplId)
|
||||
{
|
||||
this.id = aPrplId;
|
||||
}
|
||||
UnknownProtocol.prototype = {
|
||||
__proto__: ClassInfo("prplIProtocol", "Unknown protocol"),
|
||||
get name() "",
|
||||
get normalizedName() this.name,
|
||||
get iconBaseURI() "chrome://instantbird/skin/prpl-unknown/",
|
||||
getOptions: function() EmptyEnumerator,
|
||||
getUsernameSplit: function() EmptyEnumerator,
|
||||
get usernameEmptyText() "",
|
||||
|
||||
getAccount: function(aKey, aName) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
accountExists: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
|
||||
// false seems an acceptable default for all options
|
||||
// (they should never be called anyway).
|
||||
get uniqueChatName() false,
|
||||
get chatHasTopic() false,
|
||||
get noPassword() false,
|
||||
get newMailNotification() false,
|
||||
get imagesInIM() false,
|
||||
get passwordOptional() true,
|
||||
get usePointSize() true,
|
||||
get registerNoScreenName() false,
|
||||
get slashCommandsNative() false,
|
||||
get usePurpleProxy() false
|
||||
};
|
||||
|
||||
// aName and aPrplId are provided as parameter only if this is a new
|
||||
// account that doesn't exist in the preferences. In this case, these
|
||||
// 2 values should be stored.
|
||||
function imAccount(aKey, aName, aPrplId)
|
||||
{
|
||||
if (aKey.indexOf(kAccountKeyPrefix) != 0)
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
|
||||
this.id = aKey;
|
||||
this.numericId = parseInt(aKey.substr(kAccountKeyPrefix.length));
|
||||
this.prefBranch = Services.prefs.getBranch(kPrefAccountPrefix + aKey + ".");
|
||||
|
||||
if (aName) {
|
||||
this.name = aName;
|
||||
this.prefBranch.setCharPref(kPrefAccountName, aName);
|
||||
this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_UNKNOWN;
|
||||
}
|
||||
else
|
||||
this.name = this.prefBranch.getCharPref(kPrefAccountName);
|
||||
|
||||
let prplId = aPrplId;
|
||||
if (prplId)
|
||||
this.prefBranch.setCharPref(kPrefAccountPrpl, prplId);
|
||||
else
|
||||
prplId = this.prefBranch.getCharPref(kPrefAccountPrpl);
|
||||
|
||||
// Get the protocol plugin, or fallback to an UnknownProtocol instance.
|
||||
this.protocol = Services.core.getProtocolById(prplId);
|
||||
if (!this.protocol) {
|
||||
this.protocol = new UnknownProtocol(prplId);
|
||||
this._connectionErrorReason = Ci.imIAccount.ERROR_UNKNOWN_PRPL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure the account is correctly stored in blist.sqlite.
|
||||
Services.contacts.storeAccount(this.numericId, this.name, prplId);
|
||||
|
||||
// Get the prplIAccount from the protocol plugin.
|
||||
this.prplAccount = this.protocol.getAccount(this);
|
||||
|
||||
// Send status change notifications to the account.
|
||||
this.observedStatusInfo = null; // (To execute the setter).
|
||||
|
||||
// If we have never finished the first connection attempt for this account,
|
||||
// mark the account as having caused a crash.
|
||||
if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_PENDING)
|
||||
this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_CRASHED;
|
||||
|
||||
// Check for errors that should prevent connection attempts.
|
||||
if (this._passwordRequired && !this.password)
|
||||
this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD;
|
||||
else if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_CRASHED)
|
||||
this._connectionErrorReason = Ci.imIAccount.ERROR_CRASHED;
|
||||
}
|
||||
|
||||
imAccount.prototype = {
|
||||
__proto__: ClassInfo(["imIAccount", "prplIAccount"], "im account object"),
|
||||
|
||||
name: "",
|
||||
id: "",
|
||||
numericId: 0,
|
||||
protocol: null,
|
||||
prplAccount: null,
|
||||
connectionState: Ci.imIAccount.STATE_DISCONNECTED,
|
||||
connectionStateMsg: "",
|
||||
connectionErrorMessage: "",
|
||||
_connectionErrorReason: Ci.prplIAccount.NO_ERROR,
|
||||
get connectionErrorReason() {
|
||||
if (this._connectionErrorReason != Ci.prplIAccount.NO_ERROR)
|
||||
return this._connectionErrorReason;
|
||||
else
|
||||
return this.prplAccount.connectionErrorReason;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "account-connect-progress")
|
||||
this.connectionStateMsg = aData;
|
||||
else if (aTopic == "account-connecting") {
|
||||
if (this.prplAccount.connectionErrorReason != Ci.prplIAccount.NO_ERROR) {
|
||||
delete this.connectionErrorMessage;
|
||||
if (this.timeOfNextReconnect - Date.now() > 1000) {
|
||||
// This is a manual reconnection, reset the auto-reconnect stuff
|
||||
this.timeOfLastConnect = 0;
|
||||
this.cancelReconnection();
|
||||
}
|
||||
}
|
||||
if (this.firstConnectionState != Ci.imIAccount.FIRST_CONNECTION_OK)
|
||||
this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_PENDING;
|
||||
this.connectionState = Ci.imIAccount.STATE_CONNECTING;
|
||||
}
|
||||
else if (aTopic == "account-connected") {
|
||||
this.connectionState = Ci.imIAccount.STATE_CONNECTED;
|
||||
this._finishedAutoLogin();
|
||||
this.timeOfLastConnect = Date.now();
|
||||
if (this.firstConnectionState != Ci.imIAccount.FIRST_CONNECTION_OK)
|
||||
this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_OK;
|
||||
delete this.connectionStateMsg;
|
||||
}
|
||||
else if (aTopic == "account-disconnecting") {
|
||||
this.connectionState = Ci.imIAccount.STATE_DISCONNECTING;
|
||||
this.connectionErrorMessage = aData;
|
||||
delete this.connectionStateMsg;
|
||||
this._finishedAutoLogin();
|
||||
|
||||
let firstConnectionState = this.firstConnectionState;
|
||||
if (firstConnectionState != Ci.imIAccount.FIRST_CONNECTION_OK &&
|
||||
firstConnectionState != Ci.imIAccount.FIRST_CONNECTION_CRASHED)
|
||||
this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_UNKNOWN;
|
||||
|
||||
let connectionErrorReason = this.prplAccount.connectionErrorReason;
|
||||
if (connectionErrorReason != Ci.prplIAccount.NO_ERROR) {
|
||||
if (connectionErrorReason == Ci.prplIAccount.ERROR_NETWORK_ERROR ||
|
||||
connectionErrorReason == Ci.prplIAccount.ERROR_ENCRYPTION_ERROR)
|
||||
this._startReconnectTimer();
|
||||
this._sendNotification("account-connect-error");
|
||||
}
|
||||
}
|
||||
else if (aTopic == "account-disconnected")
|
||||
this.connectionState = Ci.imIAccount.STATE_DISCONNECTED;
|
||||
else
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
this._sendNotification(aTopic, aData);
|
||||
},
|
||||
|
||||
_observedStatusInfo: null,
|
||||
get observedStatusInfo() this._observedStatusInfo,
|
||||
_statusObserver: null,
|
||||
set observedStatusInfo(aUserStatusInfo) {
|
||||
if (!this.prplAccount)
|
||||
return;
|
||||
if (this._statusObserver)
|
||||
this.statusInfo.removeObserver(this._statusObserver);
|
||||
this._observedStatusInfo = aUserStatusInfo;
|
||||
if (!this._statusObserver) {
|
||||
let prplAccount = this.prplAccount;
|
||||
this._statusObserver = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
prplAccount.observe(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
}
|
||||
this.statusInfo.addObserver(this._statusObserver);
|
||||
},
|
||||
get statusInfo() this._observedStatusInfo || Services.core.globalUserStatus,
|
||||
|
||||
reconnectAttempt: 0,
|
||||
timeOfLastConnect: 0,
|
||||
timeOfNextReconnect: 0,
|
||||
_reconnectTimer: null,
|
||||
_startReconnectTimer: function() {
|
||||
/* If the last successful connection is older than 10 seconds, reset the
|
||||
number of reconnection attemps. */
|
||||
const kTimeBeforeSuccessfulConnection = 10;
|
||||
if (this.timeOfLastConnect &&
|
||||
this.timeOfLastConnect + kTimeBeforeSuccessfulConnection * 1000 < Date.now()) {
|
||||
delete this.reconnectAttempt;
|
||||
delete this.timeOfLastConnect;
|
||||
}
|
||||
|
||||
let timers =
|
||||
Services.prefs.getCharPref("messenger.accounts.reconnectTimer").split(",");
|
||||
let delay = timers[Math.max(this.reconnectAttempt, timers.length - 1)];
|
||||
let msDelay = parseInt(delay) * 1000;
|
||||
++this.reconnectAttempt;
|
||||
this.timeOfNextReconnect = Date.now() + msDelay;
|
||||
this._reconnectTimer = setTimeout(this.connect.bind(this), msDelay);
|
||||
},
|
||||
|
||||
_sendNotification: function(aTopic, aData) {
|
||||
Services.obs.notifyObservers(this, aTopic, aData);
|
||||
},
|
||||
|
||||
get firstConnectionState() {
|
||||
try {
|
||||
return this.prefBranch.getIntPref(kPrefAccountFirstConnectionState);
|
||||
} catch (e) {
|
||||
return Ci.imIAccount.FIRST_CONNECTION_OK;
|
||||
}
|
||||
},
|
||||
set firstConnectionState(aState) {
|
||||
if (aState == Ci.imIAccount.FIRST_CONNECTION_OK)
|
||||
this.prefBranch.deleteBranch(kPrefAccountFirstConnectionState);
|
||||
else {
|
||||
this.prefBranch.setIntPref(kPrefAccountFirstConnectionState, aState);
|
||||
// We want to save this pref immediately when trying to connect.
|
||||
if (aState == Ci.imIAccount.FIRST_CONNECTION_PENDING)
|
||||
SavePrefTimer.saveNow();
|
||||
else
|
||||
SavePrefTimer.initTimer();
|
||||
}
|
||||
},
|
||||
|
||||
get normalizedName() this._ensurePrplAccount.normalizedName,
|
||||
|
||||
_sendUpdateNotification: function() {
|
||||
this._sendNotification("account-updated");
|
||||
},
|
||||
|
||||
set alias(val) {
|
||||
if (val)
|
||||
this.prefBranch.setCharPref(kPrefAccountAlias, val);
|
||||
else
|
||||
this.prefBranch.deleteBranch(kPrefAccountAlias);
|
||||
this._sendUpdateNotification();
|
||||
},
|
||||
get alias() {
|
||||
try {
|
||||
return this.prefBranch.getCharPref(kPrefAccountAlias);
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
get password() {
|
||||
try {
|
||||
return this.prefBranch.getCharPref(kPrefAccountPassword);
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
get _passwordRequired()
|
||||
!this.protocol.noPassword && !this.protocol.passwordOptional,
|
||||
set password(aPassword) {
|
||||
this.prefBranch.setCharPref(kPrefAccountPassword, aPassword);
|
||||
if (aPassword &&
|
||||
this._connectionErrorReason == Ci.imIAccount.ERROR_MISSING_PASSWORD) {
|
||||
if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_CRASHED)
|
||||
this._connectionErrorReason = Ci.imIAccount.ERROR_CRASHED;
|
||||
else
|
||||
this._connectionErrorReason = Ci.imIAccount.NO_ERROR;
|
||||
}
|
||||
else if (!aPassword && this._passwordRequired)
|
||||
this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD;
|
||||
this._sendUpdateNotification();
|
||||
},
|
||||
|
||||
get autoLogin() {
|
||||
let autoLogin = true;
|
||||
try {
|
||||
autoLogin = this.prefBranch.getBoolPref(kPrefAccountAutoLogin);
|
||||
} catch (e) { }
|
||||
return autoLogin;
|
||||
},
|
||||
set autoLogin(val) {
|
||||
this.prefBranch.setBoolPref(kPrefAccountAutoLogin, val);
|
||||
SavePrefTimer.initTimer();
|
||||
this._sendUpdateNotification();
|
||||
},
|
||||
_autoLoginPending: false,
|
||||
checkAutoLogin: function() {
|
||||
// No auto-login if: the account has an error at the imIAccount level
|
||||
// (unknown protocol, missing password, first connection crashed),
|
||||
// the account is already connected or connecting, or autoLogin is off.
|
||||
if (this._connectionErrorReason != Ci.prplIAccount.NO_ERROR ||
|
||||
this.connecting || this.connected || !this.autoLogin)
|
||||
return;
|
||||
|
||||
this._autoLoginPending = true;
|
||||
AutoLoginCounter.startAutoLogin();
|
||||
try {
|
||||
this.connect();
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
this._finishedAutoLogin();
|
||||
}
|
||||
},
|
||||
_finishedAutoLogin: function() {
|
||||
if (!this.hasOwnProperty("_autoLoginPending"))
|
||||
return;
|
||||
delete this._autoLoginPending;
|
||||
AutoLoginCounter.finishedAutoLogin();
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
this.unInit();
|
||||
Services.contacts.forgetAccount(this.numericId);
|
||||
this.prefBranch.deleteBranch("");
|
||||
},
|
||||
unInit: function() {
|
||||
// remove any pending reconnection timer.
|
||||
this.cancelReconnection();
|
||||
|
||||
// remove any pending autologin preference used for crash detection.
|
||||
this._finishedAutoLogin();
|
||||
|
||||
// If the first connection was pending on quit, we set it back to unknown.
|
||||
if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_PENDING)
|
||||
this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_UNKNOWN;
|
||||
|
||||
// and make sure we cleanup the save pref timer.
|
||||
SavePrefTimer.unInitTimer();
|
||||
|
||||
if (this.prplAccount)
|
||||
this.prplAccount.unInit();
|
||||
|
||||
delete this.protocol;
|
||||
delete this.prplAccount;
|
||||
},
|
||||
|
||||
get _ensurePrplAccount() {
|
||||
if (this.prplAccount)
|
||||
return this.prplAccount;
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
connect: function() { this._ensurePrplAccount.connect(); },
|
||||
disconnect: function() { this._ensurePrplAccount.disconnect(); },
|
||||
|
||||
get disconnected() this.connectionState == Ci.imIAccount.STATE_DISCONNECTED,
|
||||
get connected() this.connectionState == Ci.imIAccount.STATE_CONNECTED,
|
||||
get connecting() this.connectionState == Ci.imIAccount.STATE_CONNECTING,
|
||||
get disconnecting() this.connectionState == Ci.imIAccount.STATE_DISCONNECTING,
|
||||
|
||||
cancelReconnection: function() {
|
||||
if (this._reconnectTimer) {
|
||||
clearTimeout(this._reconnectTimer);
|
||||
delete this._reconnectTimer;
|
||||
}
|
||||
delete this.reconnectAttempt;
|
||||
delete this.timeOfNextReconnect;
|
||||
},
|
||||
createConversation: function(aName)
|
||||
this._ensurePrplAccount.createConversation(aName),
|
||||
addBuddy: function(aTag, aName) {
|
||||
this._ensurePrplAccount.addBuddy(aTag, aName);
|
||||
},
|
||||
loadBuddy: function(aBuddy, aTag)
|
||||
this._ensurePrplAccount.loadBuddy(aBuddy, aTag), // FIXME for unknown proto
|
||||
requestBuddyInfo: function(aBuddyName) {
|
||||
this._ensurePrplAccount.requestBuddyInfo(aBuddyName);
|
||||
},
|
||||
getChatRoomFields: function() this._ensurePrplAccount.getChatRoomFields(),
|
||||
getChatRoomDefaultFieldValues: function(aDefaultChatName)
|
||||
this._ensurePrplAccount.getChatRoomDefaultFieldValues(aDefaultChatName),
|
||||
get canJoinChat() this.prplAccount ? this.prplAccount.canJoinChat : false,
|
||||
joinChat: function(aComponents) {
|
||||
this._ensurePrplAccount.joinChat(aComponents);
|
||||
},
|
||||
setBool: function(aName, aVal) {
|
||||
this.prefBranch.setBoolPref(kAccountOptionPrefPrefix + aName, aVal);
|
||||
if (this.prplAccount)
|
||||
this.prplAccount.setBool(aName, aVal);
|
||||
SavePrefTimer.initTimer();
|
||||
},
|
||||
setInt: function(aName, aVal) {
|
||||
this.prefBranch.setIntPref(kAccountOptionPrefPrefix + aName, aVal);
|
||||
if (this.prplAccount)
|
||||
this.prplAccount.setInt(aName, aVal);
|
||||
SavePrefTimer.initTimer();
|
||||
},
|
||||
setString: function(aName, aVal) {
|
||||
this.prefBranch.setCharPref(kAccountOptionPrefPrefix + aName, aVal);
|
||||
if (this.prplAccount)
|
||||
this.prplAccount.setString(aName, aVal);
|
||||
SavePrefTimer.initTimer();
|
||||
},
|
||||
save: function() { SavePrefTimer.saveNow(); },
|
||||
|
||||
get HTMLEnabled() this._ensurePrplAccount.HTMLEnabled,
|
||||
get noBackgroundColors() this._ensurePrplAccount.noBackgroundColors,
|
||||
get autoResponses() this._ensurePrplAccount.autoResponses,
|
||||
get singleFormatting() this._ensurePrplAccount.singleFormatting,
|
||||
get noNewlines() this._ensurePrplAccount.noNewlines,
|
||||
get noFontSizes() this._ensurePrplAccount.noFontSizes,
|
||||
get noUrlDesc() this._ensurePrplAccount.noUrlDesc,
|
||||
get noImages() this._ensurePrplAccount.noImages,
|
||||
get maxMessageLength() this._ensurePrplAccount.maxMessageLength,
|
||||
|
||||
get proxyInfo() this._ensurePrplAccount.proxyInfo,
|
||||
set proxyInfo(val) { this._ensurePrplAccount.proxyInfo = val; }
|
||||
};
|
||||
|
||||
function AccountsService() { }
|
||||
AccountsService.prototype = {
|
||||
initAccounts: function() {
|
||||
this._initAutoLoginStatus();
|
||||
this._accounts = [];
|
||||
this._accountsById = {};
|
||||
for each (let account in this._accountList.split(",")) {
|
||||
try {
|
||||
account.trim();
|
||||
if (!account)
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
let newAccount = new imAccount(account);
|
||||
this._accounts.push(newAccount);
|
||||
this._accountsById[newAccount.numericId] = newAccount;
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
dump(e + " " + e.toSource() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
this._prefObserver = this.observe.bind(this);
|
||||
Services.prefs.addObserver(kPrefMessengerAccounts, this._prefObserver, false);
|
||||
},
|
||||
|
||||
_observingAccountListChange: true,
|
||||
_prefObserver: null,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic != "nsPref:changed" || aData != kPrefMessengerAccounts ||
|
||||
!this._observingAccountListChange)
|
||||
return;
|
||||
|
||||
this._accounts =
|
||||
this._accountList.split(",").map(String.trim)
|
||||
.filter(function (k) k.indexOf(kAccountKeyPrefix) == 0)
|
||||
.map(function (k) parseInt(k.substr(kAccountKeyPrefix.length)))
|
||||
.map(this.getAccountByNumericId, this)
|
||||
.filter(function (a) a);
|
||||
|
||||
Services.obs.notifyObservers(this, "account-list-updated", null);
|
||||
},
|
||||
|
||||
get _accountList() Services.prefs.getCharPref(kPrefMessengerAccounts),
|
||||
set _accountList(aNewList) {
|
||||
this._observingAccountListChange = false;
|
||||
Services.prefs.setCharPref(kPrefMessengerAccounts, aNewList);
|
||||
delete this._observingAccountListChange;
|
||||
},
|
||||
|
||||
unInitAccounts: function() {
|
||||
for each (let account in this._accounts)
|
||||
account.unInit();
|
||||
delete this._accounts;
|
||||
delete this._accountsById;
|
||||
Services.prefs.removeObserver(kPrefMessengerAccounts, this._prefObserver);
|
||||
delete this._prefObserver;
|
||||
},
|
||||
|
||||
autoLoginStatus: Ci.imIAccountsService.AUTOLOGIN_ENABLED,
|
||||
_initAutoLoginStatus: function() {
|
||||
/* If auto-login is already disabled, do nothing */
|
||||
if (this.autoLoginStatus != Ci.imIAccountsService.AUTOLOGIN_ENABLED)
|
||||
return;
|
||||
|
||||
let prefs = Services.prefs;
|
||||
if (!prefs.getIntPref("messenger.startup.action")) {
|
||||
// the value 0 means that we start without connecting the accounts
|
||||
this.autoLoginStatus = Ci.imIAccountsService.AUTOLOGIN_USER_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable auto-login if we are running in safe mode */
|
||||
if (Services.appinfo.inSafeMode) {
|
||||
this.autoLoginStatus = Ci.imIAccountsService.AUTOLOGIN_SAFE_MODE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the application was started offline, disable auto-login */
|
||||
if (!Services.io.manageOfflineStatus && Services.io.offline) {
|
||||
this.autoLoginStatus = Ci.imIAccountsService.AUTOLOGIN_START_OFFLINE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we crashed at the last startup during autologin */
|
||||
let autoLoginPending;
|
||||
if (prefs.getPrefType(kPrefAutologinPending) == prefs.PREF_INVALID ||
|
||||
!(autoLoginPending = prefs.getIntPref(kPrefAutologinPending))) {
|
||||
// if the pref isn't set, then we haven't crashed: keep autologin enabled
|
||||
return;
|
||||
}
|
||||
|
||||
// Last autologin hasn't finished properly.
|
||||
// For now, assume it's because of a crash.
|
||||
this.autoLoginStatus = Ci.imIAccountsService.AUTOLOGIN_CRASH;
|
||||
prefs.deleteBranch(kPrefAutologinPending);
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
try {
|
||||
// Try to get more info with breakpad
|
||||
let lastCrashTime = 0;
|
||||
|
||||
/* Locate the LastCrash file */
|
||||
let lastCrash =
|
||||
Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties)
|
||||
.get("UAppData", Ci.nsILocalFile);
|
||||
lastCrash.append("Crash Reports");
|
||||
lastCrash.append("LastCrash");
|
||||
if (lastCrash.exists()) {
|
||||
/* Ok, the file exists, now let's try to read it */
|
||||
let is = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
let sis = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
is.init(lastCrash, -1, 0, 0);
|
||||
sstream.init(sis);
|
||||
|
||||
lastCrashTime = parseInt(sstream.read(lastCrash.fileSize));
|
||||
|
||||
sstream.close();
|
||||
fstream.close();
|
||||
}
|
||||
// The file not existing is totally acceptable, it just means that
|
||||
// either we never crashed or breakpad is not enabled.
|
||||
// In this case, lastCrashTime will keep its 0 initialization value.
|
||||
|
||||
/*dump("autoLoginPending = " + autoLoginPending +
|
||||
", lastCrash = " + lastCrashTime +
|
||||
", difference = " + lastCrashTime - autoLoginPending + "\n");*/
|
||||
|
||||
if (lastCrashTime < autoLoginPending) {
|
||||
// the last crash caught by breakpad is older than our last autologin
|
||||
// attempt.
|
||||
// If breakpad is currently enabled, we can be confident that
|
||||
// autologin was interrupted for an exterior reason
|
||||
// (application killed by the user, power outage, ...)
|
||||
try {
|
||||
Services.appinfo.QueryInterface(Ci.nsICrashReporter)
|
||||
.annotateCrashReport("=", "");
|
||||
} catch (e) {
|
||||
// This should fail with NS_ERROR_INVALID_ARG if breakpad is enabled,
|
||||
// and NS_ERROR_NOT_INITIALIZED if it is not.
|
||||
if (e != Cr.NS_ERROR_NOT_INITIALIZED)
|
||||
this.autoLoginStatus = Ci.imIAccountsService.AUTOLOGIN_ENABLED;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// if we failed to get the last crash time, then keep the
|
||||
// AUTOLOGIN_CRASH value in mAutoLoginStatus and return.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
},
|
||||
|
||||
processAutoLogin: function() {
|
||||
if (Services.io.offline)
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
|
||||
for each (let account in this._accounts)
|
||||
account.checkAutoLogin();
|
||||
|
||||
// Make sure autologin is now enabled, so that we don't display a
|
||||
// message stating that it is disabled and asking the user if it
|
||||
// should be processed now.
|
||||
this.autoLoginStatus = Ci.imIAccountsService.AUTOLOGIN_ENABLED;
|
||||
|
||||
// Notify observers so that any message stating that autologin is
|
||||
// disabled can be removed
|
||||
Services.observers(this, "autologin-processed", null);
|
||||
},
|
||||
|
||||
getAccountById: function(aAccountId) {
|
||||
if (aAccountId.indexOf(kAccountKeyPrefix) != 0)
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
|
||||
let id = parseInt(aAccountId.substr(kAccountKeyPrefix.length));
|
||||
return this.getAccountByNumericId(id);
|
||||
},
|
||||
|
||||
getAccountByNumericId: function(aAccountId) this._accountsById[aAccountId],
|
||||
getAccounts: function() new nsSimpleEnumerator(this._accounts),
|
||||
|
||||
createAccount: function(aName, aPrpl) {
|
||||
// Ensure an account with the same name and protocol doesn't already exist.
|
||||
let prpl = Services.core.getProtocolById(aPrpl);
|
||||
if (!prpl)
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
if (prpl.accountExists(aName)) {
|
||||
Cu.reportError("Attempted to create a duplicate account!");
|
||||
throw Cr.NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
/* First get a unique id for the new account. */
|
||||
let id;
|
||||
let found = true;
|
||||
for (id = 1; found; ++id) {
|
||||
if (this._accountsById.hasOwnProperty(id))
|
||||
continue;
|
||||
|
||||
/* id isn't used by a known account, double check it isn't
|
||||
already used in the sqlite database. This should never
|
||||
happen, except if we have a corrupted profile. */
|
||||
found = Services.contacts.accountIdExists(id);
|
||||
if (found)
|
||||
Services.console.logStringMessage("No account " + id + " but there is some data in the buddy list for an account with this number. Your profile may be corrupted.");
|
||||
}
|
||||
|
||||
/* Actually create the new account. */
|
||||
let key = kAccountKeyPrefix + id;
|
||||
let account = new imAccount(key, aName, aPrpl);
|
||||
|
||||
/* Keep it in the local account lists. */
|
||||
this._accounts.push(account);
|
||||
this._accountsById[id] = account;
|
||||
|
||||
/* Save the account list pref. */
|
||||
let list = this._accountList;
|
||||
this._accountList = list ? list + "," + key : key;
|
||||
|
||||
Services.obs.notifyObservers(account, "account-added", null);
|
||||
return account;
|
||||
},
|
||||
|
||||
deleteAccount: function(aAccountId) {
|
||||
let account = this.getAccountById(aAccountId);
|
||||
if (!account)
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
|
||||
let index = this._accounts.indexOf(account);
|
||||
if (index == -1)
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
|
||||
let id = account.numericId;
|
||||
Services.obs.notifyObservers(account, "account-removed", null);
|
||||
account.remove();
|
||||
this._accounts.splice(index, 1);
|
||||
delete this._accountsById[id];
|
||||
|
||||
/* Update the account list pref. */
|
||||
let list = this._accountList;
|
||||
this._accountList =
|
||||
list.split(",").filter(function (k) k.trim() != aAccountId).join(",");
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.imIAccountsService]),
|
||||
classDescription: "Accounts",
|
||||
classID: Components.ID("{a94b5427-cd8d-40cf-b47e-b67671953e70}"),
|
||||
contractID: "@instantbird.org/purple/accounts-service;1"
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([AccountsService]);
|
|
@ -0,0 +1,2 @@
|
|||
component {a94b5427-cd8d-40cf-b47e-b67671953e70} imAccounts.js
|
||||
contract @instantbird.org/purple/accounts-service;1 {a94b5427-cd8d-40cf-b47e-b67671953e70}
|
|
@ -151,7 +151,7 @@ CommandsService.prototype = {
|
|||
usageContext: Ci.imICommand.CONTEXT_ALL,
|
||||
priority: Ci.imICommand.PRIORITY_HIGH,
|
||||
run: function(aMsg) {
|
||||
Services.core.setStatus(statusValue, aMsg);
|
||||
Services.core.globalUserStatus.setStatus(statusValue, aMsg);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -39,6 +39,76 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
|||
Cu.import("resource:///modules/imXPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/imServices.jsm");
|
||||
|
||||
var gDBConnection = null;
|
||||
|
||||
function getDBConnection()
|
||||
{
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
let dbFile =
|
||||
Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties)
|
||||
.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile);
|
||||
dbFile.append("blist.sqlite");
|
||||
|
||||
let conn =
|
||||
Cc["@mozilla.org/storage/service;1"].getService(Ci.mozIStorageService)
|
||||
.openDatabase(dbFile);
|
||||
if (!conn.connectionReady)
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
|
||||
// Grow blist db in 512KB increments.
|
||||
conn.setGrowthIncrement(512 * 1024, "");
|
||||
|
||||
// Create tables and indexes.
|
||||
[
|
||||
"CREATE TABLE IF NOT EXISTS accounts (" +
|
||||
"id INTEGER PRIMARY KEY, " +
|
||||
"name VARCHAR, " +
|
||||
"prpl VARCHAR)",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS contacts (" +
|
||||
"id INTEGER PRIMARY KEY, " +
|
||||
"firstname VARCHAR, " +
|
||||
"lastname VARCHAR, " +
|
||||
"alias VARCHAR)",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS buddies (" +
|
||||
"id INTEGER PRIMARY KEY, " +
|
||||
"key VARCHAR NOT NULL, " +
|
||||
"name VARCHAR NOT NULL, " +
|
||||
"srv_alias VARCHAR, " +
|
||||
"position INTEGER, " +
|
||||
"icon BLOB, " +
|
||||
"contact_id INTEGER)",
|
||||
"CREATE INDEX IF NOT EXISTS buddies_contactindex " +
|
||||
"ON buddies (contact_id)",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS tags (" +
|
||||
"id INTEGER PRIMARY KEY, " +
|
||||
"name VARCHAR UNIQUE NOT NULL, " +
|
||||
"position INTEGER)",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS contact_tag (" +
|
||||
"contact_id INTEGER NOT NULL, " +
|
||||
"tag_id INTEGER NOT NULL)",
|
||||
"CREATE INDEX IF NOT EXISTS contact_tag_contactindex " +
|
||||
"ON contact_tag (contact_id)",
|
||||
"CREATE INDEX IF NOT EXISTS contact_tag_tagindex " +
|
||||
"ON contact_tag (tag_id)",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS account_buddy (" +
|
||||
"account_id INTEGER NOT NULL, " +
|
||||
"buddy_id INTEGER NOT NULL, " +
|
||||
"status VARCHAR, " +
|
||||
"tag_id INTEGER)",
|
||||
"CREATE INDEX IF NOT EXISTS account_buddy_accountindex " +
|
||||
"ON account_buddy (account_id)",
|
||||
"CREATE INDEX IF NOT EXISTS account_buddy_buddyindex " +
|
||||
"ON account_buddy (buddy_id)"
|
||||
].forEach(conn.executeSimpleSQL);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
// Wrap all the usage of DBConn inside a transaction that will be
|
||||
// commited automatically at the end of the event loop spin so that
|
||||
// we flush buddy list data to disk only once per event loop spin.
|
||||
|
@ -47,30 +117,17 @@ this.__defineGetter__("DBConn", function() {
|
|||
if (gDBConnWithPendingTransaction)
|
||||
return gDBConnWithPendingTransaction;
|
||||
|
||||
let conn = Services.core.storageConnection;
|
||||
gDBConnWithPendingTransaction = conn;
|
||||
conn.beginTransaction();
|
||||
if (!gDBConnection)
|
||||
gDBConnection = getDBConnection();
|
||||
gDBConnWithPendingTransaction = gDBConnection;
|
||||
gDBConnection.beginTransaction();
|
||||
executeSoon(function() {
|
||||
gDBConnWithPendingTransaction.commitTransaction();
|
||||
gDBConnWithPendingTransaction = null;
|
||||
});
|
||||
return conn;
|
||||
return gDBConnection;
|
||||
});
|
||||
|
||||
var AccountsById = { };
|
||||
function getAccountById(aId) {
|
||||
if (AccountsById.hasOwnProperty(aId))
|
||||
return AccountsById[aId];
|
||||
|
||||
let account = null;
|
||||
try {
|
||||
account = Services.core.getAccountByNumericId(aId);
|
||||
} catch (x) { /* Not found */ }
|
||||
|
||||
AccountsById[aId] = account;
|
||||
return account;
|
||||
}
|
||||
|
||||
function TagsService() { }
|
||||
TagsService.prototype = {
|
||||
get wrappedJSObject() this,
|
||||
|
@ -1154,7 +1211,8 @@ ContactsService.prototype = {
|
|||
|
||||
statement = DBConn.createStatement("SELECT account_id, buddy_id, tag_id FROM account_buddy");
|
||||
while (statement.executeStep()) {
|
||||
let account = getAccountById(statement.getInt32(0));
|
||||
let account =
|
||||
Services.accounts.getAccountByNumericId(statement.getInt32(0));
|
||||
let buddy = BuddiesById[statement.getInt32(1)];
|
||||
let tag = TagsById[statement.getInt32(2)];
|
||||
try {
|
||||
|
@ -1163,7 +1221,7 @@ ContactsService.prototype = {
|
|||
buddy._addAccount(ab, tag);
|
||||
} catch (e) {
|
||||
// FIXME ab shouldn't be NULL (once purpleAccount is finished)
|
||||
// It currently doesn't work write with unknown protocols.
|
||||
// It currently doesn't work right with unknown protocols.
|
||||
Components.utils.reportError(e);
|
||||
dump(e + "\n");
|
||||
}
|
||||
|
@ -1172,7 +1230,6 @@ ContactsService.prototype = {
|
|||
otherContactsTag._initHiddenTags();
|
||||
},
|
||||
unInitContacts: function() {
|
||||
AccountsById = { };
|
||||
Tags = [];
|
||||
TagsById = { };
|
||||
// Avoid shutdown leaks caused by references to native components
|
||||
|
@ -1266,6 +1323,45 @@ ContactsService.prototype = {
|
|||
ContactsById[buddy.contact.id]._moved(aOldTag, aNewTag);
|
||||
},
|
||||
|
||||
storeAccount: function(aId, aUserName, aPrplId) {
|
||||
let statement =
|
||||
DBConn.createStatement("SELECT name, prpl FROM accounts WHERE id = :id");
|
||||
statement.params.id = aId;
|
||||
if (statement.executeStep()) {
|
||||
if (statement.getUTF8String(0) == aUserName &&
|
||||
statement.getUTF8String(1) == aPrplId)
|
||||
return; // The account is already stored correctly.
|
||||
throw Cr.NS_ERROR_UNEXPECTED; // Corrupted database?!?
|
||||
}
|
||||
|
||||
// Actually store the account.
|
||||
statement = DBConn.createStatement("INSERT INTO accounts (id, name, prpl) " +
|
||||
"VALUES(:id, :userName, :prplId)");
|
||||
statement.params.id = aId;
|
||||
statement.params.userName = aUserName;
|
||||
statement.params.prplId = aPrplId;
|
||||
statement.execute();
|
||||
},
|
||||
accountIdExists: function(aId) {
|
||||
let statement =
|
||||
DBConn.createStatement("SELECT id FROM accounts WHERE id = :id");
|
||||
statement.params.id = aId;
|
||||
return statement.executeStep();
|
||||
},
|
||||
forgetAccount: function(aId) {
|
||||
let statement =
|
||||
DBConn.createStatement("DELETE FROM accounts WHERE id = :accountId");
|
||||
statement.params.accountId = aId;
|
||||
statement.execute();
|
||||
|
||||
// removing the account from the accounts table is not enought,
|
||||
// we need to remove all the associated account_buddy entries too
|
||||
statement = DBConn.createStatement("DELETE FROM account_buddy " +
|
||||
"WHERE account_id = :accountId");
|
||||
statement.params.accountId = aId;
|
||||
statement.execute();
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.imIContactsService]),
|
||||
classDescription: "Contacts",
|
||||
classID: Components.ID("{8c3725dd-ee26-489d-8135-736015af8c7f}"),
|
||||
|
|
|
@ -132,6 +132,7 @@ UIConversation.prototype = {
|
|||
else
|
||||
aContactId.value = 0;
|
||||
|
||||
delete this._currentTargetId;
|
||||
this.notifyObservers(this, "ui-conversation-closed");
|
||||
Services.obs.notifyObservers(this, "ui-conversation-closed", null);
|
||||
return true;
|
||||
|
@ -165,6 +166,9 @@ UIConversation.prototype = {
|
|||
return this._messages;
|
||||
},
|
||||
checkClose: function() {
|
||||
if (!this._currentTargetId)
|
||||
return true; // already closed.
|
||||
|
||||
if (!Services.prefs.getBoolPref("messenger.conversations.alwaysClose") &&
|
||||
(this.isChat && !this.left ||
|
||||
!this.isChat && this.unreadIncomingMessageCount != 0))
|
||||
|
@ -287,6 +291,7 @@ UIConversation.prototype = {
|
|||
close: function() {
|
||||
for each (let conv in this._purpleConv)
|
||||
conv.close();
|
||||
delete this._currentTargetId;
|
||||
this.notifyObservers(this, "ui-conversation-closed");
|
||||
Services.obs.notifyObservers(this, "ui-conversation-closed", null);
|
||||
},
|
||||
|
|
|
@ -0,0 +1,368 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Instantbird messenging client, released
|
||||
* 2011.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Florian QUEZE <florian@instantbird.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
Cu.import("resource:///modules/imServices.jsm");
|
||||
Cu.import("resource:///modules/imXPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "categoryManager",
|
||||
"@mozilla.org/categorymanager;1",
|
||||
"nsICategoryManager");
|
||||
|
||||
const kQuitApplicationGranted = "quit-application-granted";
|
||||
const kProtocolPluginCategory = "im-protocol-plugin";
|
||||
|
||||
const kPrefReportIdle = "messenger.status.reportIdle";
|
||||
const kPrefUserIconFilename = "messenger.status.userIconFileName";
|
||||
const kPrefUserDisplayname = "messenger.status.userDisplayName";
|
||||
const kPrefTimeBeforeIdle = "messenger.status.timeBeforeIdle";
|
||||
const kPrefAwayWhenIdle = "messenger.status.awayWhenIdle";
|
||||
const kPrefDefaultMessage = "messenger.status.defaultIdleAwayMessage";
|
||||
|
||||
const NS_IOSERVICE_GOING_OFFLINE_TOPIC = "network:offline-about-to-go-offline";
|
||||
const NS_IOSERVICE_OFFLINE_STATUS_TOPIC = "network:offline-status-changed";
|
||||
|
||||
function UserStatus()
|
||||
{
|
||||
this._observers = [];
|
||||
|
||||
if (Services.prefs.getBoolPref(kPrefReportIdle))
|
||||
this._addIdleObserver();
|
||||
Services.prefs.addObserver(kPrefReportIdle, this, false);
|
||||
|
||||
if (Services.io.offline)
|
||||
this._offline = true;
|
||||
Services.obs.addObserver(this, NS_IOSERVICE_GOING_OFFLINE_TOPIC, false);
|
||||
Services.obs.addObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC, false);
|
||||
}
|
||||
UserStatus.prototype = {
|
||||
__proto__: ClassInfo("imIUserStatusInfo", "User status info"),
|
||||
|
||||
unInit: function() {
|
||||
this._observers = [];
|
||||
Services.prefs.removeObserver(kPrefReportIdle, this);
|
||||
if (this._observingIdleness)
|
||||
this._removeIdleObserver();
|
||||
Services.obs.removeObserver(this, NS_IOSERVICE_GOING_OFFLINE_TOPIC);
|
||||
Services.obs.removeObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
|
||||
},
|
||||
_observingIdleness: false,
|
||||
_addIdleObserver: function() {
|
||||
this._observingIdleness = true;
|
||||
this._idleService =
|
||||
Cc["@mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService);
|
||||
Services.obs.addObserver(this, "im-sent", false);
|
||||
|
||||
this._timeBeforeIdle = Services.prefs.getIntPref(kPrefTimeBeforeIdle);
|
||||
if (this._timeBeforeIdle < 0)
|
||||
this._timeBeforeIdle = 0;
|
||||
Services.prefs.addObserver(kPrefTimeBeforeIdle, this, false);
|
||||
if (this._timeBeforeIdle)
|
||||
this._idleService.addIdleObserver(this, this._timeBeforeIdle);
|
||||
},
|
||||
_removeIdleObserver: function() {
|
||||
if (this._timeBeforeIdle)
|
||||
this._idleService.removeIdleObserver(this, this._timeBeforeIdle);
|
||||
|
||||
Services.prefs.removeObserver(kPrefTimeBeforeIdle, this);
|
||||
delete this._timeBeforeIdle;
|
||||
|
||||
Services.obs.removeObserver(this, "im-sent");
|
||||
delete this._idleService;
|
||||
delete this._observingIdleness;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "nsPref:changed") {
|
||||
if (aData == kPrefReportIdle) {
|
||||
let reportIdle = Services.prefs.getBoolPref(kPrefReportIdle);
|
||||
if (reportIdle && !this._observingIdleness)
|
||||
this._addIdleObserver();
|
||||
else if (!reportIdle && this._observingIdleness)
|
||||
this._removeIdleObserver();
|
||||
}
|
||||
else if (aData == kPrefTimeBeforeIdle) {
|
||||
let timeBeforeIdle = Services.prefs.getIntPref(kPrefTimeBeforeIdle);
|
||||
if (timeBeforeIdle != this._timeBeforeIdle) {
|
||||
if (this._timeBeforeIdle)
|
||||
this._idleService.removeIdleObserver(this, this._timeBeforeIdle);
|
||||
this._timeBeforeIdle = timeBeforeIdle;
|
||||
if (this._timeBeforeIdle)
|
||||
this._idleService.addIdleObserver(this, this._timeBeforeIdle);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
else if (aTopic == NS_IOSERVICE_GOING_OFFLINE_TOPIC)
|
||||
this._offline = true;
|
||||
else if (aTopic == NS_IOSERVICE_OFFLINE_STATUS_TOPIC && aData == "online")
|
||||
this._offline = false;
|
||||
else
|
||||
this._checkIdle();
|
||||
},
|
||||
|
||||
_offlineStatusType: Ci.imIStatusInfo.STATUS_AVAILABLE,
|
||||
set offline(aOffline) {
|
||||
let statusType = this.statusType;
|
||||
let statusText = this.statusText;
|
||||
if (aOffline)
|
||||
this._offlineStatusType = Ci.imIStatusInfo.STATUS_OFFLINE;
|
||||
else
|
||||
delete this._offlineStatusType;
|
||||
if (this.statusType != statusType || this.statusText != statusText)
|
||||
this._notifyObservers("status-changed", this.statusText);
|
||||
},
|
||||
|
||||
_idleTime: 0,
|
||||
get idleTime() this._idleTime,
|
||||
set idleTime(aIdleTime) {
|
||||
this._idleTime = aIdleTime;
|
||||
this._notifyObservers("idle-time-changed", aIdleTime);
|
||||
},
|
||||
_idle: false,
|
||||
_idleStatusText: "",
|
||||
_idleStatusType: Ci.imIStatusInfo.STATUS_AVAILABLE,
|
||||
_checkIdle: function() {
|
||||
let idleTime = this._idleService.idleTime / 1000;
|
||||
let idle = this._timeBeforeIdle && idleTime >= this._timeBeforeIdle;
|
||||
if (idle == this._idle)
|
||||
return;
|
||||
|
||||
let statusType = this.statusType;
|
||||
let statusText = this.statusText;
|
||||
this._idle = idle;
|
||||
if (idle) {
|
||||
this.idleTime = idleTime;
|
||||
if (Services.prefs.getBoolPref(kPrefAwayWhenIdle)) {
|
||||
this._idleStatusType = Ci.imIStatusInfo.STATUS_AWAY;
|
||||
this._idleStatusText =
|
||||
Services.prefs.getComplexValue(kPrefDefaultMessage,
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.idleTime = 0;
|
||||
delete this._idleStatusType;
|
||||
delete this._idleStatusText;
|
||||
}
|
||||
if (this.statusType != statusType || this.statusText != statusText)
|
||||
this._notifyObservers("status-changed", this.statusText);
|
||||
},
|
||||
|
||||
_statusText: "",
|
||||
get statusText() this._statusText || this._idleStatusText,
|
||||
_statusType: Ci.imIStatusInfo.STATUS_AVAILABLE,
|
||||
get statusType() Math.min(this._statusType, this._idleStatusType, this._offlineStatusType),
|
||||
setStatus: function(aStatus, aMessage) {
|
||||
if (aStatus != Ci.imIStatusInfo.STATUS_UNKNOWN)
|
||||
this._statusType = aStatus;
|
||||
if (aStatus != Ci.imIStatusInfo.STATUS_OFFLINE)
|
||||
this._statusText = aMessage;
|
||||
this._notifyObservers("status-changed", aMessage);
|
||||
},
|
||||
|
||||
_getProfileDir: function()
|
||||
Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties)
|
||||
.get("ProfD" /*NS_APP_USER_PROFILE_50_DIR*/, Ci.nsIFile),
|
||||
setUserIcon: function(aIconFile) {
|
||||
let folder = this._getProfileDir();
|
||||
|
||||
let newName = "";
|
||||
if (aIconFile) {
|
||||
// Get the extension (remove trailing dots - invalid Windows extension).
|
||||
let ext = aIconFile.leafName.replace(/.*(\.[a-z0-9]+)\.*/i, "$1");
|
||||
// newName = userIcon-<timestamp(now)>.<aIconFile.extension>
|
||||
newName = "userIcon-" + (Date.now() / 1000) + ext;
|
||||
|
||||
// Copy the new icon file to newName in the profile folder.
|
||||
aIconFile.copyTo(folder, newName);
|
||||
}
|
||||
|
||||
// Get the previous file name before saving the new file name.
|
||||
let oldFileName = Services.prefs.getCharPref(kPrefUserIconFilename);
|
||||
Services.prefs.setCharPref(kPrefUserIconFilename, newName);
|
||||
|
||||
// Now that the new icon has been copied to the profile directory
|
||||
// and the pref value changed, we can remove the old icon. Ignore
|
||||
// failures so that we always fire the user-icon-changed notification.
|
||||
try {
|
||||
if (oldFileName) {
|
||||
folder.append(oldFileName);
|
||||
if (folder.exists())
|
||||
folder.remove(false);
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
this._notifyObservers("user-icon-changed", newName);
|
||||
},
|
||||
getUserIcon: function() {
|
||||
let filename = Services.prefs.getCharPref(kPrefUserIconFilename);
|
||||
if (!filename)
|
||||
return null; // No icon has been set.
|
||||
|
||||
let file = this._getProfileDir();
|
||||
file.append(filename);
|
||||
|
||||
if (!file.exists()) {
|
||||
Services.console.logStringMessage("Invalid userIconFileName preference");
|
||||
return null;
|
||||
}
|
||||
|
||||
return Services.io.newFileURI(file);
|
||||
},
|
||||
|
||||
get displayName() Services.prefs.getCharPref(kPrefUserDisplayname),
|
||||
set displayName(aDisplayName) {
|
||||
Services.prefs.setCharPref(kPrefUserDisplayname, aDisplayName);
|
||||
this._notifyObservers("user-display-name-changed", aDisplayName);
|
||||
},
|
||||
|
||||
addObserver: function(aObserver) {
|
||||
if (this._observers.indexOf(aObserver) == -1)
|
||||
this._observers.push(aObserver);
|
||||
},
|
||||
removeObserver: function(aObserver) {
|
||||
this._observers = this._observers.filter(function(o) o !== aObserver);
|
||||
},
|
||||
_notifyObservers: function(aTopic, aData) {
|
||||
for each (let observer in this._observers)
|
||||
observer.observe(this, aTopic, aData);
|
||||
}
|
||||
};
|
||||
|
||||
var gCoreService;
|
||||
function CoreService() { gCoreService = this; }
|
||||
CoreService.prototype = {
|
||||
_initialized: false,
|
||||
globalUserStatus: null,
|
||||
init: function() {
|
||||
if (this._initialized)
|
||||
throw Cr.NS_ERROR_ALREADY_INITIALIZED;
|
||||
|
||||
Services.obs.addObserver(this, kQuitApplicationGranted, false);
|
||||
this._initialized = true;
|
||||
|
||||
Services.cmd.initCommands();
|
||||
this._protos = {};
|
||||
|
||||
this.globalUserStatus = new UserStatus();
|
||||
this.globalUserStatus.addObserver({
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.notifyObservers(aSubject, aTopic, aData);
|
||||
}
|
||||
});
|
||||
|
||||
Services.accounts.initAccounts();
|
||||
Services.contacts.initContacts();
|
||||
Services.conversations.initConversations();
|
||||
},
|
||||
observe: function(aObject, aTopic, aData) {
|
||||
if (aTopic == kQuitApplicationGranted)
|
||||
this.quit();
|
||||
},
|
||||
quit: function() {
|
||||
if (!this._initialized)
|
||||
throw Cr.NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
Services.obs.removeObserver(this, kQuitApplicationGranted);
|
||||
Services.obs.notifyObservers(this, "prpl-quit", null);
|
||||
|
||||
Services.conversations.unInitConversations();
|
||||
Services.accounts.unInitAccounts();
|
||||
Services.contacts.unInitContacts();
|
||||
Services.cmd.unInitCommands();
|
||||
|
||||
this.globalUserStatus.unInit();
|
||||
delete this.globalUserStatus;
|
||||
delete this._protos;
|
||||
delete this._initialized;
|
||||
},
|
||||
|
||||
getProtocols: function() {
|
||||
if (!this._initialized)
|
||||
throw Cr.NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
let protocols = [];
|
||||
let entries = categoryManager.enumerateCategory(kProtocolPluginCategory);
|
||||
while (entries.hasMoreElements()) {
|
||||
let id = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
|
||||
let proto = this.getProtocolById(id);
|
||||
if (proto)
|
||||
protocols.push(proto);
|
||||
}
|
||||
return new nsSimpleEnumerator(protocols);
|
||||
},
|
||||
|
||||
getProtocolById: function(aPrplId) {
|
||||
if (!this._initialized)
|
||||
throw Cr.NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (this._protos.hasOwnProperty(aPrplId))
|
||||
return this._protos[aPrplId];
|
||||
|
||||
let cid;
|
||||
try {
|
||||
cid = categoryManager.getCategoryEntry(kProtocolPluginCategory, aPrplId);
|
||||
} catch (e) {
|
||||
return null; // no protocol registered for this id.
|
||||
}
|
||||
|
||||
let proto = null;
|
||||
try {
|
||||
proto = Cc[cid].createInstance(Ci.prplIProtocol);
|
||||
} catch (e) {
|
||||
// This is a real error, the protocol is registered and failed to init.
|
||||
Cu.reportError(e);
|
||||
}
|
||||
if (!proto)
|
||||
return null;
|
||||
|
||||
proto.init(aPrplId);
|
||||
this._protos[aPrplId] = proto;
|
||||
return proto;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.imICoreService]),
|
||||
classDescription: "Core",
|
||||
classID: Components.ID("{073f5953-853c-4a38-bd81-255510c31c2e}"),
|
||||
contractID: "@instantbird.org/purple/core-service;1"
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([CoreService]);
|
|
@ -0,0 +1,2 @@
|
|||
component {073f5953-853c-4a38-bd81-255510c31c2e} imCore.js
|
||||
contract @instantbird.org/purple/core-service;1 {073f5953-853c-4a38-bd81-255510c31c2e}
|
|
@ -40,9 +40,12 @@ let EXPORTED_SYMBOLS = ["Services"];
|
|||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "accounts",
|
||||
"@instantbird.org/purple/accounts-service;1",
|
||||
"imIAccountsService");
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "core",
|
||||
"@instantbird.org/purple/core;1",
|
||||
"purpleICoreService");
|
||||
"@instantbird.org/purple/core-service;1",
|
||||
"imICoreService");
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "cmd",
|
||||
"@instantbird.org/purple/commands-service;1",
|
||||
"imICommandsService");
|
||||
|
|
|
@ -431,7 +431,7 @@ const messageReplacements = {
|
|||
|
||||
// For outgoing messages, use the current user icon.
|
||||
if (aMsg.outgoing) {
|
||||
iconURL = Services.core.getUserIcon();
|
||||
iconURL = aMsg.conversation.account.statusInfo.getUserIcon();
|
||||
if (iconURL)
|
||||
return iconURL.spec;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,11 @@ function ClassInfo(aInterfaces, aDescription)
|
|||
|
||||
if (!Array.isArray(aInterfaces))
|
||||
aInterfaces = [aInterfaces];
|
||||
|
||||
for each (let i in aInterfaces)
|
||||
if (typeof i == "string" && !(i in Ci))
|
||||
Services.console.logStringMessage("ClassInfo: unknown interface " + i);
|
||||
|
||||
this._interfaces =
|
||||
aInterfaces.map(function (i) typeof i == "string" ? Ci[i] : i);
|
||||
|
||||
|
|
|
@ -58,26 +58,18 @@ initLogModule("jsProtoHelper");
|
|||
|
||||
function normalize(aString) aString.replace(/[^a-z0-9]/gi, "").toLowerCase()
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "AccountBase", function()
|
||||
Components.Constructor("@instantbird.org/purple/account;1",
|
||||
"purpleIAccountBase")
|
||||
);
|
||||
|
||||
const ForwardAccountPrototype = {
|
||||
__proto__: ClassInfo("purpleIAccount", "generic account object"),
|
||||
_init: function _init(aProtoInstance, aBase) {
|
||||
__proto__: ClassInfo("prplIAccount", "generic account object"),
|
||||
_init: function _init(aBase) {
|
||||
this._base = aBase;
|
||||
this._base.concreteAccount = this;
|
||||
this._protocol = aProtoInstance;
|
||||
},
|
||||
get base() this._base.purpleIAccountBase,
|
||||
|
||||
checkAutoLogin: function() this._base.checkAutoLogin(),
|
||||
remove: function() this._base.remove(),
|
||||
UnInit: function() this._base.UnInit(),
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
this._base.observe(aSubject, aTopic, aData);
|
||||
},
|
||||
unInit: function() this._base.unInit(),
|
||||
connect: function() this._base.connect(),
|
||||
disconnect: function() this._base.disconnect(),
|
||||
cancelReconnection: function() this._base.cancelReconnection(),
|
||||
createConversation: function(aName) this._base.createConversation(aName),
|
||||
addBuddy: function(aTag, aName) this._base.addBuddy(aTag, aName),
|
||||
loadBuddy: function(aBuddy, aTag) this._base.loadBuddy(aBuddy, aTag),
|
||||
|
@ -89,33 +81,11 @@ const ForwardAccountPrototype = {
|
|||
setBool: function(aName, aVal) this._base.setBool(aName, aVal),
|
||||
setInt: function(aName, aVal) this._base.setInt(aName, aVal),
|
||||
setString: function(aName, aVal) this._base.setString(aName, aVal),
|
||||
save: function() this._base.save(),
|
||||
|
||||
// grep attribute purpleIAccount.idl |sed 's/.* //;s/;//;s/\(.*\)/ get \1() this._base.\1,/'
|
||||
// Exception: the protocol getter is handled locally.
|
||||
get canJoinChat() this._base.canJoinChat,
|
||||
get name() this._base.name,
|
||||
get normalizedName() this._base.normalizedName,
|
||||
get id() this._base.id,
|
||||
get numericId() this._base.numericId,
|
||||
get protocol() this._protocol,
|
||||
get autoLogin() this._base.autoLogin,
|
||||
get firstConnectionState() this._base.firstConnectionState,
|
||||
get password() this._base.password,
|
||||
get rememberPassword() this._base.rememberPassword,
|
||||
get alias() this._base.alias,
|
||||
get proxyInfo() this._base.proxyInfo,
|
||||
get connectionStateMsg() this._base.connectionStateMsg,
|
||||
get connectionErrorReason() this._base.connectionErrorReason,
|
||||
get reconnectAttempt() this._base.reconnectAttempt,
|
||||
get timeOfNextReconnect() this._base.timeOfNextReconnect,
|
||||
get timeOfLastConnect() this._base.timeOfLastConnect,
|
||||
get connectionErrorMessage() this._base.connectionErrorMessage,
|
||||
get connectionState() this._base.connectionState,
|
||||
get disconnected() this._base.disconnected,
|
||||
get connected() this._base.connected,
|
||||
get connecting() this._base.connecting,
|
||||
get disconnecting() this._base.disconnecting,
|
||||
get HTMLEnabled() this._base.HTMLEnabled,
|
||||
get noBackgroundColors() this._base.noBackgroundColors,
|
||||
get autoResponses() this._base.autoResponses,
|
||||
|
@ -126,20 +96,48 @@ const ForwardAccountPrototype = {
|
|||
get noImages() this._base.noImages,
|
||||
get maxMessageLength() this._base.maxMessageLength,
|
||||
|
||||
// grep attribute purpleIAccount.idl |grep -v readonly |sed 's/.* //;s/;//;s/\(.*\)/ set \1(val) { this._base.\1 = val; },/'
|
||||
set autoLogin(val) { this._base.autoLogin = val; },
|
||||
set firstConnectionState(val) { this._base.firstConnectionState = val; },
|
||||
set password(val) { this._base.password = val; },
|
||||
set rememberPassword(val) { this._base.rememberPassword = val; },
|
||||
set alias(val) { this._base.alias = val; },
|
||||
set proxyInfo(val) { this._base.proxyInfo = val; }
|
||||
};
|
||||
|
||||
const GenericAccountPrototype = {
|
||||
__proto__: ForwardAccountPrototype,
|
||||
_init: function _init(aProtoInstance, aKey, aName) {
|
||||
ForwardAccountPrototype._init.call(this, aProtoInstance, new AccountBase());
|
||||
this._base.init(aKey, aName, aProtoInstance);
|
||||
__proto__: ClassInfo("prplIAccount", "generic account object"),
|
||||
_init: function _init(aProtocol, aImAccount) {
|
||||
this.protocol = aProtocol;
|
||||
this.imAccount = aImAccount;
|
||||
},
|
||||
observe: function(aSubject, aTopic, aData) {},
|
||||
unInit: function() {},
|
||||
connect: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
disconnect: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
createConversation: function(aName) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
joinChat: function(aComponents) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
setBool: function(aName, aVal) {},
|
||||
setInt: function(aName, aVal) {},
|
||||
setString: function(aName, aVal) {},
|
||||
|
||||
get name() this.imAccount.name,
|
||||
get connected() this.imAccount.connected,
|
||||
get connecting() this.imAccount.connecting,
|
||||
get disconnected() this.imAccount.disconnected,
|
||||
get disconnecting() this.imAccount.disconnecting,
|
||||
_connectionErrorReason: Ci.prplIAccount.NO_ERROR,
|
||||
get connectionErrorReason() this._connectionErrorReason,
|
||||
|
||||
reportConnected: function() {
|
||||
this.imAccount.observe(this, "account-connected", null);
|
||||
},
|
||||
reportConnecting: function(aConnectionStateMsg) {
|
||||
if (!this.connecting)
|
||||
this.imAccount.observe(this, "account-connecting", null);
|
||||
if (aConnectionStateMsg)
|
||||
this.imAccount.observe(this, "account-connect-progress", aConnectionStateMsg);
|
||||
},
|
||||
reportDisconnected: function() {
|
||||
this.imAccount.observe(this, "account-disconnected", null);
|
||||
},
|
||||
reportDisconnecting: function(aConnectionErrorReason, aConnectionErrorMessage) {
|
||||
this._connectionErrorReason = aConnectionErrorReason;
|
||||
this.imAccount.observe(this, "account-disconnecting", aConnectionErrorMessage);
|
||||
},
|
||||
|
||||
addBuddy: function(aTag, aName) {
|
||||
|
@ -148,13 +146,14 @@ const GenericAccountPrototype = {
|
|||
},
|
||||
loadBuddy: function(aBuddy, aTag) {
|
||||
try {
|
||||
return new AccountBuddy(this, aBuddy, aTag) ;
|
||||
return new AccountBuddy(this, aBuddy, aTag);
|
||||
} catch (x) {
|
||||
dump(x + "\n");
|
||||
return null;
|
||||
}
|
||||
},
|
||||
requestBuddyInfo: function(aBuddyName) {},
|
||||
get canJoinChat() false,
|
||||
getChatRoomFields: function() {
|
||||
if (!this.chatRoomFields)
|
||||
return EmptyEnumerator;
|
||||
|
@ -190,12 +189,22 @@ const GenericAccountPrototype = {
|
|||
getBool: function(aName) this.getPref(aName, "Bool"),
|
||||
|
||||
get prefs() this._prefs ||
|
||||
(this._prefs = Services.prefs.getBranch("messenger.account." + this.id +
|
||||
".options.")),
|
||||
(this._prefs = Services.prefs.getBranch("messenger.account." +
|
||||
this.imAccount.id + ".options.")),
|
||||
|
||||
get normalizedName() normalize(this.name),
|
||||
get proxyInfo() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
set proxyInfo(val) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
|
||||
set proxyInfo(val) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
|
||||
|
||||
get HTMLEnabled() true,
|
||||
get noBackgroundColors() true,
|
||||
get autoResponses() false,
|
||||
get singleFormatting() false,
|
||||
get noNewlines() false,
|
||||
get noFontSizes() false,
|
||||
get noUrlDesc() false,
|
||||
get noImages() true,
|
||||
get maxMessageLength() 0
|
||||
};
|
||||
|
||||
|
||||
|
@ -206,7 +215,7 @@ const GenericAccountBuddyPrototype = {
|
|||
throw "aUserName is required when aBuddy is null";
|
||||
|
||||
this._tag = aTag;
|
||||
this._account = aAccount;
|
||||
this._account = aAccount.imAccount;
|
||||
this._buddy = aBuddy;
|
||||
this._userName = aUserName;
|
||||
},
|
||||
|
@ -371,7 +380,7 @@ const GenericConversationPrototype = {
|
|||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
|
||||
_init: function(aAccount, aName) {
|
||||
this.account = aAccount;
|
||||
this.account = aAccount.imAccount;
|
||||
this._name = aName;
|
||||
this._observers = [];
|
||||
Services.conversations.addConversation(this);
|
||||
|
@ -597,8 +606,12 @@ ChatRoomFieldValues.prototype = {
|
|||
|
||||
// the name getter needs to be implemented
|
||||
const GenericProtocolPrototype = {
|
||||
__proto__: ClassInfo("purpleIProtocol", "Generic protocol object"),
|
||||
__proto__: ClassInfo("prplIProtocol", "Generic protocol object"),
|
||||
|
||||
init: function(aId) {
|
||||
if (aId != this.id)
|
||||
throw NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
get id() "prpl-" + this.normalizedName,
|
||||
get normalizedName() normalize(this.name),
|
||||
get iconBaseURI() "chrome://instantbird/skin/prpl-generic/",
|
||||
|
@ -671,9 +684,9 @@ const GenericProtocolPrototype = {
|
|||
get contractID() "@instantbird.org/purple/" + this.normalizedName + ";1"
|
||||
};
|
||||
|
||||
function ForwardAccount(aProtocol, aBaseAccount)
|
||||
function ForwardAccount(aBaseAccount)
|
||||
{
|
||||
this._init(aProtocol, aBaseAccount);
|
||||
this._init(aBaseAccount);
|
||||
}
|
||||
ForwardAccount.prototype = ForwardAccountPrototype;
|
||||
|
||||
|
@ -687,8 +700,8 @@ const ForwardProtocolPrototype = {
|
|||
this._base = Services.core.getProtocolById(this.baseId);
|
||||
return this._base;
|
||||
},
|
||||
getAccount: function(aKey, aName)
|
||||
new ForwardAccount(this, this.base.getAccount(aKey, aName)),
|
||||
getAccount: function(aImAccount)
|
||||
new ForwardAccount(this.base.getAccount(aImAccount)),
|
||||
|
||||
get iconBaseURI() this.base.iconBaseURI,
|
||||
getOptions: function() this.base.getOptions(),
|
||||
|
|
|
@ -66,9 +66,9 @@ Conversation.prototype = {
|
|||
};
|
||||
Conversation.prototype.__proto__ = GenericConvIMPrototype;
|
||||
|
||||
function Account(aProtoInstance, aKey, aName)
|
||||
function Account(aProtoInstance, aImAccount)
|
||||
{
|
||||
this._init(aProtoInstance, aKey, aName);
|
||||
this._init(aProtoInstance, aImAccount);
|
||||
}
|
||||
Account.prototype = {
|
||||
connect: function() {
|
||||
|
@ -118,7 +118,7 @@ jsTestProtocol.prototype = {
|
|||
{label: "Server", separator: "@", defaultValue: "default.server",
|
||||
reverse: true}
|
||||
],
|
||||
getAccount: function(aKey, aName) new Account(this, aKey, aName),
|
||||
getAccount: function(aImAccount) new Account(this, aImAccount),
|
||||
classID: Components.ID("{a0774c5a-4aea-458b-9fbc-8d3cbf1a4630}"),
|
||||
};
|
||||
jsTestProtocol.prototype.__proto__ = GenericProtocolPrototype;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
component {a0774c5a-4aea-458b-9fbc-8d3cbf1a4630} jsTestProtocol.js
|
||||
contract @instantbird.org/purple/jstest;1 {a0774c5a-4aea-458b-9fbc-8d3cbf1a4630}
|
||||
category js-protocol-plugin @instantbird.org/purple/jstest;1 @instantbird.org/purple/jstest;1
|
||||
category im-protocol-plugin prpl-jstest @instantbird.org/purple/jstest;1
|
||||
component {88795348-8a4b-4018-890d-5314cb08ec4d} jsTestProtocol.js
|
||||
contract @instantbird.org/purple/override;1 {88795348-8a4b-4018-890d-5314cb08ec4d}
|
||||
category js-protocol-plugin @instantbird.org/purple/override;1 @instantbird.org/purple/override;1
|
||||
category im-protocol-plugin prpl-override @instantbird.org/purple/override;1
|
||||
|
|
|
@ -61,10 +61,10 @@ facebookProtocol.prototype = {
|
|||
get iconBaseURI() "chrome://prpl-facebook/skin/",
|
||||
get baseId() "prpl-jabber",
|
||||
|
||||
getAccount: function(aKey, aName) {
|
||||
let account = ForwardProtocolPrototype.getAccount.call(this, aKey, aName);
|
||||
getAccount: function(aImAccount) {
|
||||
let account = ForwardProtocolPrototype.getAccount.call(this, aImAccount);
|
||||
account.__defineGetter__("canJoinChat", function() false);
|
||||
account.setString("connection_security", "opportunistic_tls");
|
||||
aImAccount.setString("connection_security", "opportunistic_tls");
|
||||
return account;
|
||||
},
|
||||
getOptions: function() EmptyEnumerator,
|
||||
|
|
|
@ -50,11 +50,11 @@ gtalkProtocol.prototype = {
|
|||
get iconBaseURI() "chrome://prpl-gtalk/skin/",
|
||||
get baseId() "prpl-jabber",
|
||||
|
||||
getAccount: function(aKey, aName) {
|
||||
let account = ForwardProtocolPrototype.getAccount.call(this, aKey, aName);
|
||||
getAccount: function(aImAccount) {
|
||||
let account = ForwardProtocolPrototype.getAccount.call(this, aImAccount);
|
||||
let connectServer =
|
||||
/@g(oogle)?mail.com(\/|$)/.test(aName) ? "" : "talk.google.com";
|
||||
account.setString("connect_server", connectServer);
|
||||
/@g(oogle)?mail.com(\/|$)/.test(aImAccount.name) ? "" : "talk.google.com";
|
||||
aImAccount.setString("connect_server", connectServer);
|
||||
return account;
|
||||
},
|
||||
getOptions: function() EmptyEnumerator,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
component {ad8a6454-2f5a-40c2-86ca-30062408125e} gtalkOverrideProtocol.js
|
||||
contract @instantbird.org/purple/gtalk;1 {ad8a6454-2f5a-40c2-86ca-30062408125e}
|
||||
category js-protocol-plugin @instantbird.org/purple/gtalk;1 @instantbird.org/purple/gtalk;1
|
||||
category im-protocol-plugin prpl-gtalk @instantbird.org/purple/gtalk;1
|
||||
component {61bc3528-df53-4481-a61a-74c3a2e8c9fd} facebookOverrideProtocol.js
|
||||
contract @instantbird.org/purple/facebook;1 {61bc3528-df53-4481-a61a-74c3a2e8c9fd}
|
||||
category js-protocol-plugin @instantbird.org/purple/facebook;1 @instantbird.org/purple/facebook;1
|
||||
category im-protocol-plugin prpl-facebook @instantbird.org/purple/facebook;1
|
||||
|
|
|
@ -318,13 +318,11 @@ Conversation.prototype = {
|
|||
get nick() "@" + this.account.name
|
||||
};
|
||||
|
||||
function Account(aProtoInstance, aKey, aName)
|
||||
function Account(aProtocol, aImAccount)
|
||||
{
|
||||
this._init(aProtoInstance, aKey, aName);
|
||||
this._init(aProtocol, aImAccount);
|
||||
this._knownMessageIds = {};
|
||||
this._userInfo = {};
|
||||
|
||||
Services.obs.addObserver(this, "status-changed", false);
|
||||
}
|
||||
Account.prototype = {
|
||||
__proto__: GenericAccountPrototype,
|
||||
|
@ -352,7 +350,7 @@ Account.prototype = {
|
|||
if (this.connected || this.connecting)
|
||||
return;
|
||||
|
||||
this.base.connecting();
|
||||
this.reportConnecting();
|
||||
this._enabled = true;
|
||||
|
||||
// Read the OAuth token from the prefs
|
||||
|
@ -380,12 +378,15 @@ Account.prototype = {
|
|||
this.getTimelines();
|
||||
},
|
||||
|
||||
// Currently only used for "status-changed" notification.
|
||||
observe: function(aSubject, aTopic, aMsg) {
|
||||
// Currently only used for "status-changed" notification.
|
||||
if (aTopic != "status-changed")
|
||||
return;
|
||||
|
||||
if (!this._enabled)
|
||||
return;
|
||||
|
||||
let statusType = aSubject.currentStatusType;
|
||||
let statusType = aSubject.statusType;
|
||||
if (statusType == Ci.imIStatusInfo.STATUS_OFFLINE) {
|
||||
// This will remove the _enabled value...
|
||||
this.disconnect();
|
||||
|
@ -516,8 +517,7 @@ Account.prototype = {
|
|||
},
|
||||
|
||||
getTimelines: function() {
|
||||
this.base
|
||||
.connecting(_("connection.requestTimelines"));
|
||||
this.reportConnecting(_("connection.requestTimelines"));
|
||||
|
||||
// If we have a last known message ID, append it as a get parameter.
|
||||
let lastMsgParam = this.prefs.prefHasUserValue("lastMessageId") ?
|
||||
|
@ -644,7 +644,7 @@ Account.prototype = {
|
|||
if (this._timelineAuthError)
|
||||
delete this._timelineAuthError;
|
||||
|
||||
this.base.connected();
|
||||
this.reportConnected();
|
||||
|
||||
// If the conversation already exists, notify it we are back online.
|
||||
if (this._timeline)
|
||||
|
@ -686,7 +686,7 @@ Account.prototype = {
|
|||
},
|
||||
onStreamError: function(aError) {
|
||||
delete this._streamingRequest;
|
||||
this.gotDisconnected(this._base.ERROR_NETWORK_ERROR, aError);
|
||||
this.gotDisconnected(Ci.prplIAccount.ERROR_NETWORK_ERROR, aError);
|
||||
},
|
||||
onDataAvailable: function(aRequest) {
|
||||
let text = aRequest.target.responseText;
|
||||
|
@ -734,7 +734,7 @@ Account.prototype = {
|
|||
},
|
||||
|
||||
requestToken: function() {
|
||||
this.base.connecting(_("connection.initAuth"));
|
||||
this.reportConnecting(_("connection.initAuth"));
|
||||
let oauthParams =
|
||||
[["oauth_callback", encodeURIComponent(this.completionURI)]];
|
||||
this.signAndSend("oauth/request_token", null, [],
|
||||
|
@ -746,7 +746,7 @@ Account.prototype = {
|
|||
let data = this._parseURLData(aData);
|
||||
if (!data.oauth_callback_confirmed ||
|
||||
!data.oauth_token || !data.oauth_token_secret) {
|
||||
this.gotDisconnected(this._base.ERROR_OTHER_ERROR,
|
||||
this.gotDisconnected(Ci.prplIAccount.ERROR_OTHER_ERROR,
|
||||
_("connection.failedToken"));
|
||||
return;
|
||||
}
|
||||
|
@ -756,7 +756,7 @@ Account.prototype = {
|
|||
this.requestAuthorization();
|
||||
},
|
||||
requestAuthorization: function() {
|
||||
this.base.connecting(_("connection.requestAuth"));
|
||||
this.reportConnecting(_("connection.requestAuth"));
|
||||
const url = this.baseURI + "oauth/authorize?oauth_token=";
|
||||
this._browserRequest = {
|
||||
get promptText() _("authPrompt"),
|
||||
|
@ -768,7 +768,7 @@ Account.prototype = {
|
|||
return;
|
||||
|
||||
this.account
|
||||
.gotDisconnected(this.account._base.ERROR_AUTHENTICATION_FAILED,
|
||||
.gotDisconnected(Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED,
|
||||
_("connection.error.authCancelled"));
|
||||
},
|
||||
loaded: function(aWindow, aWebProgress) {
|
||||
|
@ -825,14 +825,14 @@ Account.prototype = {
|
|||
onAuthorizationReceived: function(aData) {
|
||||
let data = this._parseURLData(aData.split("?")[1]);
|
||||
if (data.oauth_token != this.token || !data.oauth_verifier) {
|
||||
this.gotDisconnected(this._base.ERROR_OTHER_ERROR,
|
||||
this.gotDisconnected(Ci.prplIAccount.ERROR_OTHER_ERROR,
|
||||
_("connection.error.authFailed"));
|
||||
return;
|
||||
}
|
||||
this.requestAccessToken(data.oauth_verifier);
|
||||
},
|
||||
requestAccessToken: function(aTokenVerifier) {
|
||||
this.base.connecting(_("connection.requestAccess"));
|
||||
this.reportConnecting(_("connection.requestAccess"));
|
||||
this.signAndSend("oauth/access_token", null, [],
|
||||
this.onAccessTokenReceived, this.onError, this,
|
||||
[["oauth_verifier", aTokenVerifier]]);
|
||||
|
@ -878,16 +878,16 @@ Account.prototype = {
|
|||
return;
|
||||
|
||||
if (aError === undefined)
|
||||
aError = this._base.NO_ERROR;
|
||||
aError = Ci.prplIAccount.NO_ERROR;
|
||||
let connected = this.connected;
|
||||
this.base.disconnecting(aError, aErrorMessage);
|
||||
this.reportDisconnecting(aError, aErrorMessage);
|
||||
this.cleanUp();
|
||||
if (this._timeline && connected)
|
||||
this._timeline.notifyObservers(this._timeline, "update-conv-chatleft");
|
||||
delete this._enabled;
|
||||
this.base.disconnected();
|
||||
this.reportDisconnected();
|
||||
},
|
||||
UnInit: function() {
|
||||
unInit: function() {
|
||||
this.cleanUp();
|
||||
// If we've received any messages, update the last known message.
|
||||
let newestMessageId = "";
|
||||
|
@ -900,8 +900,6 @@ Account.prototype = {
|
|||
}
|
||||
if (newestMessageId)
|
||||
this.prefs.setCharPref("lastMessageId", newestMessageId);
|
||||
Services.obs.removeObserver(this, "status-changed");
|
||||
this._base.UnInit();
|
||||
},
|
||||
disconnect: function() {
|
||||
this.gotDisconnected();
|
||||
|
@ -909,11 +907,11 @@ Account.prototype = {
|
|||
|
||||
onError: function(aException) {
|
||||
if (aException == "offline") {
|
||||
this.gotDisconnected(this._base.ERROR_NETWORK_ERROR,
|
||||
this.gotDisconnected(Ci.prplIAccount.ERROR_NETWORK_ERROR,
|
||||
_("connection.error.noNetwork"));
|
||||
}
|
||||
else
|
||||
this.gotDisconnected(this._base.ERROR_OTHER_ERROR, aException.toString());
|
||||
this.gotDisconnected(Ci.prplIAccount.ERROR_OTHER_ERROR, aException.toString());
|
||||
},
|
||||
|
||||
onRequestedInfoReceived: function(aData) {
|
||||
|
@ -987,7 +985,7 @@ TwitterProtocol.prototype = {
|
|||
options: {
|
||||
"track": {get label() _("options.track"), default: ""}
|
||||
},
|
||||
getAccount: function(aKey, aName) new Account(this, aKey, aName),
|
||||
getAccount: function(aImAccount) new Account(this, aImAccount),
|
||||
classID: Components.ID("{31082ff6-1de8-422b-ab60-ca0ac0b2af13}")
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
component {31082ff6-1de8-422b-ab60-ca0ac0b2af13} twitter.js
|
||||
contract @instantbird.org/purple/twitter;1 {31082ff6-1de8-422b-ab60-ca0ac0b2af13}
|
||||
category js-protocol-plugin @instantbird.org/purple/twitter;1 @instantbird.org/purple/twitter;1
|
||||
category im-protocol-plugin prpl-twitter @instantbird.org/purple/twitter;1
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource:///modules/imServices.jsm");
|
||||
Cu.import("resource:///modules/imXPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/ibCore.jsm");
|
||||
|
||||
|
@ -51,9 +52,8 @@ ibCommandLineHandler.prototype = {
|
|||
}
|
||||
|
||||
if (cmdLine.handleFlag("n", false)) {
|
||||
Components.classes["@instantbird.org/purple/core;1"]
|
||||
.getService(Ci.purpleICoreService)
|
||||
.autoLoginStatus = Ci.purpleICoreService.AUTOLOGIN_USER_DISABLED;
|
||||
Services.accounts.autoLoginStatus =
|
||||
Ci.imIAccountsService.AUTOLOGIN_USER_DISABLED;
|
||||
}
|
||||
|
||||
// Initialize the core only at the first real startup,
|
||||
|
|
|
@ -60,8 +60,8 @@ StatusCLH.prototype = {
|
|||
cmdLine.removeArguments(statusIndex, statusIndex + 1);
|
||||
|
||||
// We're keeping the old status message here.
|
||||
Services.core.setStatus(Status.toFlag(statusParam),
|
||||
Services.core.currentStatusMessage);
|
||||
let us = Services.core.globalUserStatus;
|
||||
us.setStatus(Status.toFlag(statusParam), us.statusText);
|
||||
|
||||
// Only perform the default action (i.e. loading the buddy list) if
|
||||
// Instantbird is launched with a status flag.
|
||||
|
|
|
@ -128,8 +128,8 @@ var gMinTrayR = {
|
|||
},
|
||||
|
||||
setStatus: function MinTrayR_setStatus(aStatusParam) {
|
||||
Services.core.setStatus(Status.toFlag(aStatusParam),
|
||||
Services.core.currentStatusMessage);
|
||||
let us = Services.core.globalUserStatus;
|
||||
us.setStatus(Status.toFlag(aStatusParam), us.statusText);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
versionField.value = versionField.value + xai.platformVersion
|
||||
+ ' (' + xai.platformBuildID + ')';
|
||||
|
||||
var pcs = Components.classes["@instantbird.org/purple/core;1"]
|
||||
var pcs = Components.classes["@instantbird.org/libpurple/core;1"]
|
||||
.getService(Components.interfaces.purpleICoreService)
|
||||
versionField = document.getElementById("libpurpleVersionField");
|
||||
versionField.value = versionField.value + pcs.version;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
const autoJoinPref = "autoJoin";
|
||||
|
||||
const events = [
|
||||
"purple-quit"
|
||||
"prpl-quit"
|
||||
];
|
||||
|
||||
var account = {
|
||||
|
@ -94,7 +94,7 @@ var account = {
|
|||
removeObservers(account, events);
|
||||
},
|
||||
observe: function account_observe(aObject, aTopic, aData) {
|
||||
if (aTopic == "purple-quit") {
|
||||
if (aTopic == "prpl-quit") {
|
||||
// libpurple is being uninitialized. Close this dialog.
|
||||
window.close();
|
||||
}
|
||||
|
@ -106,7 +106,8 @@ var account = {
|
|||
var proxy;
|
||||
var result;
|
||||
if (type == Ci.purpleIProxyInfo.useGlobal) {
|
||||
proxy = Services.core.globalProxy;
|
||||
proxy = Cc["@instantbird.org/libpurple/core;1"]
|
||||
.getService(Ci.purpleICoreService).globalProxy;
|
||||
type = proxy.type;
|
||||
}
|
||||
else
|
||||
|
@ -322,7 +323,7 @@ var account = {
|
|||
|
||||
if (connectionInfoHasChanged) {
|
||||
/* This is the first time we try to connect with these parameters */
|
||||
this.account.firstConnectionState = this.account.FIRST_CONNECTION_SET;
|
||||
this.account.firstConnectionState = this.account.FIRST_CONNECTION_UNKNOWN;
|
||||
|
||||
if (this.account.connecting) {
|
||||
this.account.disconnect();
|
||||
|
@ -331,10 +332,10 @@ var account = {
|
|||
}
|
||||
let errorReason = this.account.connectionErrorReason;
|
||||
if (this.account.disconnected &&
|
||||
errorReason != Ci.purpleIAccount.NO_ERROR &&
|
||||
errorReason != Ci.purpleIAccount.ERROR_MISSING_PASSWORD &&
|
||||
errorReason != Ci.purpleIAccount.ERROR_CRASHED &&
|
||||
errorReason != Ci.purpleIAccount.ERROR_UNKNOWN_PRPL) {
|
||||
errorReason != Ci.prplIAccount.NO_ERROR &&
|
||||
errorReason != Ci.imIAccount.ERROR_MISSING_PASSWORD &&
|
||||
errorReason != Ci.imIAccount.ERROR_CRASHED &&
|
||||
errorReason != Ci.imIAccount.ERROR_UNKNOWN_PRPL) {
|
||||
this.account.connect();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
this.refreshConnectedLabel();
|
||||
} else if (this._account.disconnected) {
|
||||
state = "disconnected";
|
||||
if (this._account.connectionErrorReason != Ci.purpleIAccount.NO_ERROR)
|
||||
if (this._account.connectionErrorReason != Ci.prplIAccount.NO_ERROR)
|
||||
this.updateConnectionError();
|
||||
else
|
||||
this.removeAttribute("error");
|
||||
|
@ -136,12 +136,12 @@
|
|||
var account = this._account;
|
||||
var text;
|
||||
let errorReason = account.connectionErrorReason;
|
||||
if (errorReason == Ci.purpleIAccount.ERROR_UNKNOWN_PRPL)
|
||||
if (errorReason == Ci.imIAccount.ERROR_UNKNOWN_PRPL)
|
||||
text = bundle.getFormattedString(key + "UnknownPrpl",
|
||||
[account.protocol.id]);
|
||||
else if (errorReason == Ci.purpleIAccount.ERROR_MISSING_PASSWORD)
|
||||
else if (errorReason == Ci.imIAccount.ERROR_MISSING_PASSWORD)
|
||||
text = bundle.getString(key + "MissingPassword");
|
||||
else if (errorReason == Ci.purpleIAccount.ERROR_CRASHED)
|
||||
else if (errorReason == Ci.imIAccount.ERROR_CRASHED)
|
||||
text = bundle.getString(key + "CrashedAccount");
|
||||
else
|
||||
text = account.connectionErrorMessage;
|
||||
|
@ -230,7 +230,7 @@
|
|||
this._connectedLabel = null;
|
||||
if (this._account.connected)
|
||||
this.refreshConnectedLabel();
|
||||
if (this._account.connectionErrorReason == Ci.purpleIAccount.NO_ERROR)
|
||||
if (this._account.connectionErrorReason == Ci.prplIAccount.NO_ERROR)
|
||||
this.updateConnectionState();
|
||||
else
|
||||
this.updateConnectionError();
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
const PREF_EXTENSIONS_GETMOREPROTOCOLSURL = "extensions.getMoreProtocolsURL";
|
||||
|
||||
const events = [
|
||||
"purple-quit"
|
||||
"prpl-quit"
|
||||
];
|
||||
|
||||
var accountWizard = {
|
||||
|
@ -70,7 +70,7 @@ var accountWizard = {
|
|||
removeObservers(accountWizard, events);
|
||||
},
|
||||
observe: function am_observe(aObject, aTopic, aData) {
|
||||
if (aTopic == "purple-quit") {
|
||||
if (aTopic == "prpl-quit") {
|
||||
// libpurple is being uninitialized. We can't create any new
|
||||
// account so keeping this wizard open would be pointless, close it.
|
||||
window.close();
|
||||
|
@ -222,7 +222,8 @@ var accountWizard = {
|
|||
var proxy;
|
||||
var result;
|
||||
if (type == Ci.purpleIProxyInfo.useGlobal) {
|
||||
proxy = Services.core.globalProxy;
|
||||
proxy = Cc["@instantbird.org/libpurple/core;1"]
|
||||
.getService(Ci.purpleICoreService).globalProxy;
|
||||
type = proxy.type;
|
||||
}
|
||||
else
|
||||
|
@ -438,11 +439,9 @@ var accountWizard = {
|
|||
},
|
||||
|
||||
createAccount: function aw_createAccount() {
|
||||
var acc = Services.core.createAccount(this.username, this.proto.id);
|
||||
if (!this.proto.noPassword) {
|
||||
var acc = Services.accounts.createAccount(this.username, this.proto.id);
|
||||
if (!this.proto.noPassword)
|
||||
acc.password = this.password;
|
||||
acc.rememberPassword = true;
|
||||
}
|
||||
if (this.alias)
|
||||
acc.alias = this.alias;
|
||||
//FIXME: newMailNotification
|
||||
|
|
|
@ -40,7 +40,7 @@ Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
|||
|
||||
// This is the list of notifications that the account manager window observes
|
||||
const events = [
|
||||
"purple-quit",
|
||||
"prpl-quit",
|
||||
"account-list-updated",
|
||||
"account-added",
|
||||
"account-updated",
|
||||
|
@ -126,7 +126,7 @@ var gAccountManager = {
|
|||
this.disableCommandItems();
|
||||
},
|
||||
observe: function am_observe(aObject, aTopic, aData) {
|
||||
if (aTopic == "purple-quit") {
|
||||
if (aTopic == "prpl-quit") {
|
||||
// libpurple is being uninitialized. We don't need the account
|
||||
// manager window anymore, close it.
|
||||
this.close();
|
||||
|
@ -144,7 +144,7 @@ var gAccountManager = {
|
|||
return;
|
||||
}
|
||||
else if (aTopic == "status-changed") {
|
||||
this.setOffline(aObject.currentStatusType == Ci.imIStatusInfo.STATUS_OFFLINE);
|
||||
this.setOffline(aObject.statusType == Ci.imIStatusInfo.STATUS_OFFLINE);
|
||||
return;
|
||||
}
|
||||
else if (aTopic == "account-list-updated") {
|
||||
|
@ -152,8 +152,8 @@ var gAccountManager = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(aObject instanceof Ci.purpleIAccount))
|
||||
throw "Bad notification.";
|
||||
// The following notification handlers need an account.
|
||||
aObject.QueryInterface(Ci.imIAccount);
|
||||
|
||||
if (aTopic == "account-added") {
|
||||
document.getElementById("accountsDesk").selectedIndex = 1;
|
||||
|
@ -203,6 +203,9 @@ var gAccountManager = {
|
|||
};
|
||||
if (aTopic in stateEvents) {
|
||||
let elt = document.getElementById(aObject.id);
|
||||
if (!elt)
|
||||
return; // probably disconnecting a removed account.
|
||||
|
||||
if (aTopic == "account-connecting") {
|
||||
elt.removeAttribute("error");
|
||||
elt.updateConnectionState();
|
||||
|
@ -283,7 +286,7 @@ var gAccountManager = {
|
|||
Services.prefs.setBoolPref("messenger.accounts.promptOnDelete", false);
|
||||
}
|
||||
|
||||
Services.core.deleteAccount(selectedItem.id);
|
||||
Services.accounts.deleteAccount(selectedItem.id);
|
||||
},
|
||||
new: function am_new() {
|
||||
this.openDialog("chrome://instantbird/content/accountWizard.xul");
|
||||
|
@ -326,8 +329,8 @@ var gAccountManager = {
|
|||
let isCommandDisabled =
|
||||
(this.isOffline ||
|
||||
(account.disconnected &&
|
||||
(account.connectionErrorReason == Ci.purpleIAccount.ERROR_UNKNOWN_PRPL ||
|
||||
account.connectionErrorReason == Ci.purpleIAccount.ERROR_MISSING_PASSWORD)));
|
||||
(account.connectionErrorReason == Ci.imIAccount.ERROR_UNKNOWN_PRPL ||
|
||||
account.connectionErrorReason == Ci.imIAccount.ERROR_MISSING_PASSWORD)));
|
||||
|
||||
[[activeCommandElt, isCommandDisabled],
|
||||
[document.getElementById("cmd_moveup"), accountList.selectedIndex == 0],
|
||||
|
@ -446,7 +449,7 @@ var gAccountManager = {
|
|||
Services.prefs.setCharPref("messenger.accounts", array.join(","));
|
||||
},
|
||||
|
||||
getAccounts: function am_getAccounts() getIter(Services.core.getAccounts()),
|
||||
getAccounts: function am_getAccounts() getIter(Services.accounts.getAccounts()),
|
||||
|
||||
openDialog: function am_openDialog(aUrl, aArgs) {
|
||||
this.modalDialog = true;
|
||||
|
@ -454,17 +457,17 @@ var gAccountManager = {
|
|||
this.modalDialog = false;
|
||||
},
|
||||
setAutoLoginNotification: function am_setAutoLoginNotification() {
|
||||
var pcs = Services.core;
|
||||
var autoLoginStatus = pcs.autoLoginStatus;
|
||||
var as = Services.accounts;
|
||||
var autoLoginStatus = as.autoLoginStatus;
|
||||
let isOffline = false;
|
||||
let crashCount = 0;
|
||||
for (let acc in this.getAccounts())
|
||||
if (acc.autoLogin && acc.firstConnectionState == acc.FIRST_CONNECTION_CRASHED)
|
||||
++crashCount;
|
||||
|
||||
if (autoLoginStatus == pcs.AUTOLOGIN_ENABLED && crashCount == 0) {
|
||||
this.setOffline(isOffline ||
|
||||
pcs.currentStatusType == Ci.imIStatusInfo.STATUS_OFFLINE);
|
||||
if (autoLoginStatus == as.AUTOLOGIN_ENABLED && crashCount == 0) {
|
||||
let status = Services.core.globalUserStatus.statusType;
|
||||
this.setOffline(isOffline || status == Ci.imIStatusInfo.STATUS_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -479,27 +482,27 @@ var gAccountManager = {
|
|||
var label;
|
||||
|
||||
switch (autoLoginStatus) {
|
||||
case pcs.AUTOLOGIN_USER_DISABLED:
|
||||
case as.AUTOLOGIN_USER_DISABLED:
|
||||
label = bundle.getString("accountsManager.notification.userDisabled.label");
|
||||
break;
|
||||
|
||||
case pcs.AUTOLOGIN_SAFE_MODE:
|
||||
case as.AUTOLOGIN_SAFE_MODE:
|
||||
label = bundle.getString("accountsManager.notification.safeMode.label");
|
||||
break;
|
||||
|
||||
case pcs.AUTOLOGIN_START_OFFLINE:
|
||||
case as.AUTOLOGIN_START_OFFLINE:
|
||||
label = bundle.getString("accountsManager.notification.startOffline.label");
|
||||
isOffline = true;
|
||||
break;
|
||||
|
||||
case pcs.AUTOLOGIN_CRASH:
|
||||
case as.AUTOLOGIN_CRASH:
|
||||
label = bundle.getString("accountsManager.notification.crash.label");
|
||||
priority = box.PRIORITY_WARNING_MEDIUM;
|
||||
break;
|
||||
|
||||
/* One or more accounts made the application crash during their connection.
|
||||
If none, this function has already returned */
|
||||
case pcs.AUTOLOGIN_ENABLED:
|
||||
case as.AUTOLOGIN_ENABLED:
|
||||
if (!("PluralForm" in window))
|
||||
Components.utils.import("resource://gre/modules/PluralForm.jsm");
|
||||
label = bundle.getString("accountsManager.notification.singleCrash.label");
|
||||
|
@ -511,8 +514,8 @@ var gAccountManager = {
|
|||
default:
|
||||
label = bundle.getString("accountsManager.notification.other.label");
|
||||
}
|
||||
this.setOffline(isOffline ||
|
||||
pcs.currentStatusType == Ci.imIStatusInfo.STATUS_OFFLINE);
|
||||
let status = Services.core.globalUserStatus.statusType;
|
||||
this.setOffline(isOffline || status == Ci.imIStatusInfo.STATUS_OFFLINE);
|
||||
|
||||
box.appendNotification(label, "autologinStatus", null, priority, [connectNowButton]);
|
||||
},
|
||||
|
@ -523,7 +526,7 @@ var gAccountManager = {
|
|||
ioService.offline = false;
|
||||
}
|
||||
|
||||
Services.core.processAutoLogin();
|
||||
Services.accounts.processAutoLogin();
|
||||
|
||||
gAccountManager.accountList.selectedItem.buttons.setFocus();
|
||||
},
|
||||
|
|
|
@ -44,7 +44,7 @@ var addBuddy = {
|
|||
|
||||
buildAccountList: function ab_buildAccountList() {
|
||||
var accountList = document.getElementById("accountlist");
|
||||
for (let acc in getIter(Services.core.getAccounts())) {
|
||||
for (let acc in getIter(Services.accounts.getAccounts())) {
|
||||
if (!acc.connected)
|
||||
continue;
|
||||
var proto = acc.protocol;
|
||||
|
@ -76,7 +76,7 @@ var addBuddy = {
|
|||
getValue: function ab_getValue(aId) document.getElementById(aId).value,
|
||||
|
||||
create: function ab_create() {
|
||||
var account = Services.core.getAccountById(this.getValue("accountlist"));
|
||||
var account = Services.accounts.getAccountById(this.getValue("accountlist"));
|
||||
var name = this.getValue("name");
|
||||
|
||||
var tag;
|
||||
|
|
|
@ -48,7 +48,7 @@ const events = ["contact-availability-changed",
|
|||
"ui-conversation-hidden",
|
||||
"user-display-name-changed",
|
||||
"user-icon-changed",
|
||||
"purple-quit"];
|
||||
"prpl-quit"];
|
||||
|
||||
const showOfflineBuddiesPref = "messenger.buddies.showOffline";
|
||||
|
||||
|
@ -313,7 +313,7 @@ buddyListContextMenu.prototype = {
|
|||
|
||||
var buddyList = {
|
||||
observe: function bl_observe(aSubject, aTopic, aMsg) {
|
||||
if (aTopic == "purple-quit") {
|
||||
if (aTopic == "prpl-quit") {
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
@ -400,12 +400,12 @@ var buddyList = {
|
|||
},
|
||||
|
||||
displayUserIcon: function bl_displayUserIcon() {
|
||||
let icon = Services.core.getUserIcon();
|
||||
let icon = Services.core.globalUserStatus.getUserIcon();
|
||||
document.getElementById("userIcon").src = icon ? icon.spec : "";
|
||||
},
|
||||
|
||||
displayUserDisplayName: function bl_displayUserDisplayName() {
|
||||
let displayName = Services.core.userDisplayName;
|
||||
let displayName = Services.core.globalUserStatus.displayName;
|
||||
let elt = document.getElementById("displayName");
|
||||
if (displayName)
|
||||
elt.removeAttribute("usingDefault");
|
||||
|
@ -428,9 +428,9 @@ var buddyList = {
|
|||
},
|
||||
|
||||
displayCurrentStatus: function bl_displayCurrentStatus() {
|
||||
let pcs = Services.core;
|
||||
let status = Status.toAttribute(pcs.currentStatusType);
|
||||
let message = status == "offline" ? "" : pcs.currentStatusMessage;
|
||||
let us = Services.core.globalUserStatus;
|
||||
let status = Status.toAttribute(us.statusType);
|
||||
let message = status == "offline" ? "" : us.statusText;
|
||||
let statusString = this.displayStatusType(status);
|
||||
let statusMessage = document.getElementById("statusMessage");
|
||||
if (message)
|
||||
|
@ -446,7 +446,7 @@ var buddyList = {
|
|||
editStatus: function bl_editStatus(aEvent) {
|
||||
let status = aEvent.originalTarget.getAttribute("status");
|
||||
if (status == "offline")
|
||||
Services.core.setStatus(Ci.imIStatusInfo.STATUS_OFFLINE, "");
|
||||
Services.core.globalUserStatus.setStatus(Ci.imIStatusInfo.STATUS_OFFLINE, "");
|
||||
else if (status)
|
||||
this.startEditStatus(status);
|
||||
},
|
||||
|
@ -476,7 +476,7 @@ var buddyList = {
|
|||
if (elt.hasAttribute("usingDefault")) {
|
||||
if ("_statusTypeBeforeEditing" in this &&
|
||||
this._statusTypeBeforeEditing == "offline")
|
||||
elt.setAttribute("value", Services.core.currentStatusMessage);
|
||||
elt.setAttribute("value", Services.core.globalUserStatus.statusMessage);
|
||||
else
|
||||
elt.removeAttribute("value");
|
||||
}
|
||||
|
@ -540,7 +540,7 @@ var buddyList = {
|
|||
// apply the new status only if it is different from the current one
|
||||
if (newStatus != Ci.imIStatusInfo.STATUS_UNKNOWN ||
|
||||
elt.value != elt.getAttribute("value"))
|
||||
Services.core.setStatus(newStatus, elt.value);
|
||||
Services.core.globalUserStatus.setStatus(newStatus, elt.value);
|
||||
}
|
||||
else if ("_statusTypeBeforeEditing" in this) {
|
||||
this.displayStatusType(this._statusTypeBeforeEditing);
|
||||
|
@ -565,7 +565,7 @@ var buddyList = {
|
|||
nsIFilePicker.modeOpen);
|
||||
fp.appendFilters(nsIFilePicker.filterImages);
|
||||
if (fp.show() == nsIFilePicker.returnOK)
|
||||
Services.core.setUserIcon(fp.file);
|
||||
Services.core.globalUserStatus.setUserIcon(fp.file);
|
||||
},
|
||||
|
||||
displayNameClick: function bl_displayNameClick() {
|
||||
|
@ -617,7 +617,7 @@ var buddyList = {
|
|||
let elt = document.getElementById("displayName");
|
||||
// Apply the new display name only if it is different from the current one.
|
||||
if (aSave && elt.value != elt.getAttribute("value"))
|
||||
Services.core.userDisplayName = elt.value;
|
||||
Services.core.globalUserStatus.displayName = elt.value;
|
||||
else if (elt.hasAttribute("usingDefault"))
|
||||
elt.setAttribute("value", elt.getAttribute("usingDefault"));
|
||||
|
||||
|
|
|
@ -66,12 +66,11 @@ function debug_enumerateProtocols()
|
|||
|
||||
function debug_connectAccount(aProto, aName, aPassword)
|
||||
{
|
||||
var pcs = Services.core;
|
||||
var proto = pcs.getProtocolById(aProto);
|
||||
var proto = Services.core.getProtocolById(aProto);
|
||||
if (!proto)
|
||||
throw "Couldn't get protocol " + aProto;
|
||||
|
||||
var acc = pcs.createAccount(aName, proto);
|
||||
var acc = Services.accounts.createAccount(aName, proto);
|
||||
acc.password = aPassword;
|
||||
dump("trying to connect to " + proto.name +
|
||||
" (" + proto.id + ") with " + aName + "\n");
|
||||
|
@ -82,7 +81,7 @@ function debug_dumpBuddyList()
|
|||
{
|
||||
let formatBuddy = (function(buddy) " " + buddy.name + "\n " + buddy.getAccounts().map(function(a) a.name).join(" "));
|
||||
let formatGroup = (function(aGroup) " Group " + aGroup.id + ": " + aGroup.name + "\n" + aGroup.getBuddies().map(formatBuddy).join("\n"));
|
||||
dump("Buddy list:\n\n" + Services.core.getTags().map(formatGroup).join("\n\n") + "\n\n");
|
||||
dump("Buddy list:\n\n" + Services.tags.getTags().map(formatGroup).join("\n\n") + "\n\n");
|
||||
}
|
||||
|
||||
function dumpStack(offset, max_depth)
|
||||
|
|
|
@ -303,12 +303,12 @@ var fake = {
|
|||
new Message("Florian", "Thanks :)",
|
||||
{time: makeDate("10:44:12"), incoming: true, conversation: chat});
|
||||
|
||||
Services.core.userDisplayName = "Tom Smith";
|
||||
Services.core.globalUserStatus.displayName = "Tom Smith";
|
||||
// Ugly :-(
|
||||
document.getElementById("userIcon").src = ib_icon_url;
|
||||
},
|
||||
deleteAccounts: function f_deleteAccounts() {
|
||||
if (!Services.core.getAccounts().hasMoreElements())
|
||||
if (!Services.accounts.getAccounts().hasMoreElements())
|
||||
return;
|
||||
|
||||
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
|
@ -317,8 +317,8 @@ var fake = {
|
|||
"You are about to delete " + nbaccounts + " accounts. Are you sure?"))
|
||||
throw "user aborted the operation";
|
||||
|
||||
for (let acc in getIter(Services.core.getAccounts()))
|
||||
Services.core.deleteAccount(acc.id);
|
||||
for (let acc in getIter(Services.accounts.getAccounts()))
|
||||
Services.accounts.deleteAccount(acc.id);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -334,7 +334,7 @@ function Account(aName, aProto)
|
|||
dump("account " + aName + " created\n");
|
||||
}
|
||||
Account.prototype = {
|
||||
__proto__: ClassInfo("purpleIAccount", "generic account object"),
|
||||
__proto__: ClassInfo("imIAccount", "generic account object"),
|
||||
protocol: null,
|
||||
password: "",
|
||||
autoLogin: true,
|
||||
|
|
|
@ -174,5 +174,5 @@ var joinChat = {
|
|||
return true;
|
||||
},
|
||||
|
||||
getAccounts: function jc_getAccounts() getIter(Services.core.getAccounts())
|
||||
getAccounts: function jc_getAccounts() getIter(Services.accounts.getAccounts())
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ var menus = {
|
|||
supportsCommand: function(aCmd)
|
||||
aCmd == "cmd_addbuddy" || aCmd == "cmd_joinchat",
|
||||
isCommandEnabled: function(aCmd) {
|
||||
let enumerator = Services.core.getAccounts();
|
||||
let enumerator = Services.accounts.getAccounts();
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let acc = enumerator.getNext();
|
||||
if (acc.connected && (aCmd == "cmd_addbuddy" || acc.canJoinChat))
|
||||
|
@ -176,7 +176,7 @@ var menus = {
|
|||
checkCurrentStatusType: function menu_checkCurrentStatusType(aItems) {
|
||||
if (!("Status" in window))
|
||||
Components.utils.import("resource:///modules/imStatusUtils.jsm");
|
||||
let status = Status.toAttribute(Services.core.currentStatusType);
|
||||
let status = Status.toAttribute(Services.core.globalUserStatus.statusType);
|
||||
if (status == "away")
|
||||
status = "unavailable";
|
||||
|
||||
|
@ -206,8 +206,8 @@ var menus = {
|
|||
blist.buddyList.startEditStatus(status);
|
||||
}
|
||||
else {
|
||||
Services.core.setStatus(Status.toFlag(status),
|
||||
Services.core.currentStatusMessage);
|
||||
let us = Services.core.globalUserStatus;
|
||||
us.setStatus(Status.toFlag(status), us.statusText);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -42,7 +42,8 @@ var gProxies = {
|
|||
// see what the global settings are
|
||||
// build a list of existing proxies
|
||||
|
||||
var pcs = Services.core;
|
||||
var pcs = Cc["@instantbird.org/libpurple/core;1"]
|
||||
.getService(Ci.purpleICoreService);
|
||||
|
||||
var proxyInfoCtr = Components.Constructor("@instantbird.org/purple/proxyinfo;1",
|
||||
"purpleIProxyInfo");
|
||||
|
@ -152,7 +153,8 @@ var gProxies = {
|
|||
},
|
||||
|
||||
accept: function proxy_accept() {
|
||||
var pcs = Services.core;
|
||||
var pcs = Cc["@instantbird.org/libpurple/core;1"]
|
||||
.getService(Ci.purpleICoreService);
|
||||
var promptService = Services.prompt;
|
||||
var item = document.getElementById("proxylist").selectedItem;
|
||||
if (item.id == "newProxy") {
|
||||
|
|
|
@ -2,11 +2,9 @@ startupFailure.title=Instantbird - Start up failure
|
|||
startupFailure.apologize=Instantbird encountered a serious error and cannot start, we apologize for the inconvenience.
|
||||
startupFailure.update=An updated version will probably be available shortly to fix the problem.
|
||||
|
||||
startupFailure.purplexpcomFileError=Description: The file "purplexpcom.xpt" is missing or corrupted.
|
||||
startupFailure.xpcomRegistrationError=Description: XPCOM registration of the purplexpcom component failed.
|
||||
startupFailure.purplexpcomInitError=An exception occurred while initializing purplexpcom: %S
|
||||
startupFailure.libpurpleError=An error occurred while checking whether libpurple is usable.
|
||||
startupFailure.noProtocolLoaded=Description: No protocol plugin could be loaded.
|
||||
startupFailure.purplexpcomFileError=Description: The file "instantbird.xpt" is missing or corrupted.
|
||||
startupFailure.xpcomRegistrationError=Description: XPCOM registration of the core component failed.
|
||||
startupFailure.purplexpcomInitError=An exception occurred while initializing the core component: %S
|
||||
|
||||
startupFailure.buttonUpdate=Check for Updates
|
||||
startupFailure.buttonClose=Close Instantbird
|
||||
|
|
|
@ -70,32 +70,19 @@ var Core = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!Components.classes["@instantbird.org/purple/core;1"]) {
|
||||
if (!Components.classes["@instantbird.org/purple/core-service;1"]) {
|
||||
this._promptError("startupFailure.xpcomRegistrationError");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var pcs = Services.core;
|
||||
pcs.init();
|
||||
Services.core.init();
|
||||
}
|
||||
catch (e) {
|
||||
this._promptError("startupFailure.purplexpcomInitError", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pcs.version) {
|
||||
this._promptError("startupFailure.libpurpleError");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pcs.getProtocols().hasMoreElements()) {
|
||||
this._promptError("startupFailure.noProtocolLoaded");
|
||||
this.uninitPurpleCore();
|
||||
return false;
|
||||
}
|
||||
|
||||
Services.conversations.initConversations();
|
||||
Conversations.init();
|
||||
Notifications.init();
|
||||
Sounds.init();
|
||||
|
@ -170,7 +157,7 @@ var Core = {
|
|||
while (aEnumerator.hasMoreElements())
|
||||
yield aEnumerator.getNext();
|
||||
},
|
||||
getAccounts: function() this.getIter(Services.core.getAccounts()),
|
||||
getAccounts: function() this.getIter(Services.accounts.getAccounts()),
|
||||
|
||||
/* This function pops up the account manager if no account is
|
||||
* connected or connecting.
|
||||
|
@ -180,7 +167,7 @@ var Core = {
|
|||
_showAccountManagerIfNeeded: function (aIsStarting) {
|
||||
// If the current status is offline, we don't need the account manager
|
||||
let isOffline =
|
||||
Services.core.currentStatusType == Ci.imIStatusInfo.STATUS_OFFLINE;
|
||||
Services.core.globalUserStatus.statusType == Ci.imIStatusInfo.STATUS_OFFLINE;
|
||||
if (isOffline && !aIsStarting)
|
||||
return;
|
||||
|
||||
|
@ -206,7 +193,7 @@ var Core = {
|
|||
|
||||
observe: function(aSubject, aTopic, aMsg) {
|
||||
if (aTopic == "account-connected") {
|
||||
let account = aSubject.QueryInterface(Components.interfaces.purpleIAccount);
|
||||
let account = aSubject.QueryInterface(Ci.imIAccount);
|
||||
if (!account.canJoinChat)
|
||||
return;
|
||||
|
||||
|
@ -225,7 +212,7 @@ var Core = {
|
|||
}
|
||||
|
||||
if (aTopic == "account-disconnected") {
|
||||
let account = aSubject.QueryInterface(Ci.purpleIAccount);
|
||||
let account = aSubject.QueryInterface(Ci.imIAccount);
|
||||
if (account.reconnectAttempt <= 1)
|
||||
this._showAccountManagerIfNeeded(false);
|
||||
return;
|
||||
|
|
|
@ -37,14 +37,14 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface purpleIAccount;
|
||||
interface imIAccount;
|
||||
interface nsIDOMWindowInternal;
|
||||
interface nsIWebProgress;
|
||||
|
||||
[scriptable, uuid(b89dbb38-0de4-11e0-b3d0-0002e304243c)]
|
||||
interface purpleIRequestBrowser: nsISupports {
|
||||
readonly attribute AUTF8String promptText;
|
||||
readonly attribute purpleIAccount account;
|
||||
readonly attribute imIAccount account;
|
||||
readonly attribute AUTF8String url;
|
||||
void cancelled();
|
||||
void loaded(in nsIDOMWindowInternal aWindow,
|
||||
|
|
Загрузка…
Ссылка в новой задаче