aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYana Stamcheva <yana@jitsi.org>2012-04-04 12:13:03 +0000
committerYana Stamcheva <yana@jitsi.org>2012-04-04 12:13:03 +0000
commitf9a8da4458d7f9d10a415d0605bc809860dc20ad (patch)
tree5b9f0ede3f5af9eb1672a6d9f71e00e29677cc38
parentf26b85ff9ed73e950c454fb855e9a2b1f4201333 (diff)
downloadjitsi-f9a8da4458d7f9d10a415d0605bc809860dc20ad.zip
jitsi-f9a8da4458d7f9d10a415d0605bc809860dc20ad.tar.gz
jitsi-f9a8da4458d7f9d10a415d0605bc809860dc20ad.tar.bz2
Adds new improved security interface.
-rw-r--r--resources/colors/colors.properties11
-rw-r--r--resources/config/defaults.properties2
-rwxr-xr-xresources/images/impl/gui/buttons/encrypted_verified.pngbin543 -> 1020 bytes
-rw-r--r--resources/images/impl/gui/buttons/goingSecureAudio.pngbin0 -> 554 bytes
-rw-r--r--resources/images/impl/gui/buttons/goingSecureVideo.pngbin0 -> 553 bytes
-rw-r--r--resources/images/impl/gui/buttons/secureAudioOff.pngbin736 -> 587 bytes
-rw-r--r--resources/images/impl/gui/buttons/secureAudioOn.pngbin781 -> 687 bytes
-rw-r--r--resources/images/impl/gui/buttons/secureVideoOff.pngbin579 -> 584 bytes
-rw-r--r--resources/images/impl/gui/buttons/secureVideoOn.pngbin585 -> 655 bytes
-rw-r--r--resources/languages/resources.properties28
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPeerAdapter.java2
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java17
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java540
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/ParanoiaTimerSecurityPanel.java142
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java78
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java178
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/ZrtpSecurityPanel.java569
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java71
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java24
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java209
-rw-r--r--src/net/java/sip/communicator/util/swing/FadeInBalloonPanel.java190
-rw-r--r--src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java2
22 files changed, 1579 insertions, 484 deletions
diff --git a/resources/colors/colors.properties b/resources/colors/colors.properties
index c8b6f44..54e6e9c 100644
--- a/resources/colors/colors.properties
+++ b/resources/colors/colors.properties
@@ -203,4 +203,13 @@ service.gui.SEARCH_BORDER_GRADIENT=ACACAC
service.gui.SEARCH_FOREGROUND=000000
# The default text foreground of the search field
-service.gui.SEARCH_DEFAULT_FOREGROUND=ACACAC \ No newline at end of file
+service.gui.SEARCH_DEFAULT_FOREGROUND=ACACAC
+
+# The security on status color.
+service.gui.SECURITY_ON=6FC93C
+
+# The security off status color.
+service.gui.SECURITY_OFF=ED0000
+
+# Going secure status color.
+service.gui.GOING_SECURE=FFC01B \ No newline at end of file
diff --git a/resources/config/defaults.properties b/resources/config/defaults.properties
index 8b285b5..51ea8c0 100644
--- a/resources/config/defaults.properties
+++ b/resources/config/defaults.properties
@@ -89,3 +89,5 @@ net.java.sip.communicator.util.dns.DS_ROOT.1=. IN DS 19036 8 2 49AAC11D7B6F64467
plugin.jabberaccregwizz.NEW_ACCOUNT_DEFAULT_SERVER=jit.si
net.java.sip.communicator.service.neomedia.SDES_CIPHER_SUITES=AES_CM_128_HMAC_SHA1_80,AES_CM_128_HMAC_SHA1_32
+
+impl.gui.PARANOIA_UI=false \ No newline at end of file
diff --git a/resources/images/impl/gui/buttons/encrypted_verified.png b/resources/images/impl/gui/buttons/encrypted_verified.png
index d5ba163..c9fd25f 100755
--- a/resources/images/impl/gui/buttons/encrypted_verified.png
+++ b/resources/images/impl/gui/buttons/encrypted_verified.png
Binary files differ
diff --git a/resources/images/impl/gui/buttons/goingSecureAudio.png b/resources/images/impl/gui/buttons/goingSecureAudio.png
new file mode 100644
index 0000000..6e019bb
--- /dev/null
+++ b/resources/images/impl/gui/buttons/goingSecureAudio.png
Binary files differ
diff --git a/resources/images/impl/gui/buttons/goingSecureVideo.png b/resources/images/impl/gui/buttons/goingSecureVideo.png
new file mode 100644
index 0000000..9e610a6
--- /dev/null
+++ b/resources/images/impl/gui/buttons/goingSecureVideo.png
Binary files differ
diff --git a/resources/images/impl/gui/buttons/secureAudioOff.png b/resources/images/impl/gui/buttons/secureAudioOff.png
index 201e782..d32800c 100644
--- a/resources/images/impl/gui/buttons/secureAudioOff.png
+++ b/resources/images/impl/gui/buttons/secureAudioOff.png
Binary files differ
diff --git a/resources/images/impl/gui/buttons/secureAudioOn.png b/resources/images/impl/gui/buttons/secureAudioOn.png
index 7bbbb51..c408c4f 100644
--- a/resources/images/impl/gui/buttons/secureAudioOn.png
+++ b/resources/images/impl/gui/buttons/secureAudioOn.png
Binary files differ
diff --git a/resources/images/impl/gui/buttons/secureVideoOff.png b/resources/images/impl/gui/buttons/secureVideoOff.png
index 546aaad..d4d144b 100644
--- a/resources/images/impl/gui/buttons/secureVideoOff.png
+++ b/resources/images/impl/gui/buttons/secureVideoOff.png
Binary files differ
diff --git a/resources/images/impl/gui/buttons/secureVideoOn.png b/resources/images/impl/gui/buttons/secureVideoOn.png
index 489784b..4f020a6 100644
--- a/resources/images/impl/gui/buttons/secureVideoOn.png
+++ b/resources/images/impl/gui/buttons/secureVideoOn.png
Binary files differ
diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties
index 80f467c..934f590 100644
--- a/resources/languages/resources.properties
+++ b/resources/languages/resources.properties
@@ -120,12 +120,11 @@ service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} has changed the subject to {1}
service.gui.CHOOSE_CONTACT=Choose contact
service.gui.CHOOSE_ACCOUNT=Please select one of the listed accounts.
service.gui.SHOW_MORE_TOOLTIP=Click to show more results
+servoce.gui.CLEAR=Clear
service.gui.CLOSE=Cl&ose
service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=You have received a new message less than 2 seconds ago. Are you sure you want to close this chat?
service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=You have active file transfers. Are you sure you want to cancel them?
-service.gui.COMPARE_WITH_PARTNER=Compare with partner and click the padlock to confirm.
-# keep the following string short
-service.gui.COMPARE_WITH_PARTNER_SHORT=Compare with partner: {0}
+servoce.gui.CONFIRM=Confirm
service.gui.CONNECTED_STATUS=Connected
service.gui.CONNECTING=Connecting...
service.gui.CONNECTING_STATUS=Connecting
@@ -611,6 +610,29 @@ service.gui.AUTO_ANSWER_DESCR_VLUE=leave empty for any
service.gui.AUTO_ANSWER_FWD_CALLS=Forward Calls
service.gui.AUTO_ANSWER_FWD_CALLS_TO=Forward all calls to the following number or URI:
+service.gui.security.SECURE_AUDIO=Secure audio
+service.gui.security.AUDIO_NOT_SECURED=Audio not secured
+service.gui.security.SECURE_VIDEO=Secure video
+service.gui.security.VIDEO_NOT_SECURED=Video not secured
+service.gui.security.NO_VIDEO=No video
+service.gui.security.CIPHER=Cipher: {0}
+service.gui.security.CALL_SECURED_TOOLTIP=Call secured. Fore more information press here.
+service.gui.security.CALL_NOT_SECURED_TOOLTIP=Call not secured. Fore more information press here.
+service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Press here to compare security secret with your partner.
+service.gui.security.COMPARE_WITH_PARTNER=Compare with partner and click the padlock to confirm.
+# keep the following string short
+service.gui.security.COMPARE_WITH_PARTNER_SHORT=Compare with partner:
+service.gui.security.STRING_COMPARED=String compared!
+service.gui.security.SAS_INFO_TOOLTIP=\
+<html>In order to be completely secured you<br/>\
+need to verbally <b>compare</b> the short<br/>\
+authentication string here left with your<br/>\
+partner and press the confirm button when the <br/>\
+string is verified.<br/><br/\
+If you clear the confirmation, you'll be asked to verify<br/>\
+next time when you call this partner.</html>
+service.gui.security.SECURITY_ALERT=Trying to secure call. Will disconnect in
+
service.gui.avatar.CHOOSE_ICON=Choose picture
service.gui.avatar.REMOVE_ICON=Remove current picture
service.gui.avatar.CLEAR_RECENT=Clear recent pictures
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerAdapter.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerAdapter.java
index 6be7282..537e4ed 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerAdapter.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerAdapter.java
@@ -104,7 +104,7 @@ public class CallPeerAdapter
renderer.getCallPanel().updateHoldButtonState();
}
- renderer.setPeerState(newStateString);
+ renderer.setPeerState(newState, newStateString);
String reasonString = evt.getReasonString();
if (reasonString != null)
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java
index d915536..ee2afd6 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java
@@ -8,6 +8,7 @@ package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
+import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
/**
@@ -37,9 +38,10 @@ public interface CallPeerRenderer
* Sets the state of the contained call peer by specifying the
* state name.
*
+ * @param peerState the peer state
* @param state the state of the contained call peer
*/
- public void setPeerState(String state);
+ public void setPeerState(CallPeerState peerState, String state);
/**
* Sets the reason of a call failure if one occurs. The renderer should
@@ -78,6 +80,11 @@ public interface CallPeerRenderer
public void securityOff(CallPeerSecurityOffEvent evt);
/**
+ * Indicates that the security status is pending confirmation.
+ */
+ public void securityPending();
+
+ /**
* Indicates that the security is timeouted, is not supported by the
* other end.
* @param evt Details about the event that caused this message.
@@ -148,4 +155,12 @@ public interface CallPeerRenderer
* @return the video handler associated with this call peer renderer
*/
public UIVideoHandler getVideoHandler();
+
+ /**
+ * Shows/hides the security panel.
+ *
+ * @param isVisible <tt>true</tt> to show the security panel, <tt>false</tt>
+ * to hide it
+ */
+ public void setSecurityPanelVisible(boolean isVisible);
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
index 3082178..2fb7267 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
@@ -14,9 +14,11 @@ import java.util.List; // disambiguation
import javax.swing.*;
import javax.swing.text.*;
+import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.call.conference.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.resources.*;
@@ -65,7 +67,7 @@ public class OneToOneCallPeerPanel
/**
* The security status of the peer
*/
- private SecurityStatusLabel securityStatusLabel;
+ private SecurityStatusLabel securityStatusLabel = new SecurityStatusLabel();
/**
* The label showing whether the voice has been set to mute.
@@ -199,6 +201,7 @@ public class OneToOneCallPeerPanel
this.callPeer = callPeer;
this.peerName = callPeer.getDisplayName();
this.videoContainers = videoContainers;
+ this.securityPanel = SecurityPanel.create(this, callPeer, null);
if (vHandler == null)
videoHandler
@@ -212,11 +215,6 @@ public class OneToOneCallPeerPanel
videoHandler.addVideoListener();
videoHandler.addRemoteControlListener();
- securityStatusLabel = new SecurityStatusLabel(
- callRenderer.getCallContainer().getCallWindow().getFrame(),
- new ImageIcon(
- ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF)));
-
photoLabel = new JLabel(getPhotoLabelIcon());
center = createCenter(videoContainers);
statusBar = createStatusBar();
@@ -382,6 +380,8 @@ public class OneToOneCallPeerPanel
statusPanel.add(muteStatusLabel, constraints);
constraints.gridx++;
+ callStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 3, 2, 5));
statusPanel.add(callStatusLabel, constraints);
constraints.gridx++;
@@ -509,7 +509,6 @@ public class OneToOneCallPeerPanel
public PeerStatusPanel(LayoutManager layout)
{
super(layout);
- this.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
}
/**
@@ -600,11 +599,25 @@ public class OneToOneCallPeerPanel
* Sets the state of the contained call peer by specifying the
* state name and icon.
*
+ * @param peerState the peer state
* @param state the state of the contained call peer
*/
- public void setPeerState(String state)
+ public void setPeerState(CallPeerState peerState, String state)
{
this.callStatusLabel.setText(state);
+
+ if (peerState == CallPeerState.CONNECTED)
+ {
+ initSecurityStatusLabel();
+
+ if(Boolean.parseBoolean(GuiActivator.getResources()
+ .getSettingsString("impl.gui.PARANOIA_UI")))
+ {
+ securityPanel = new ParanoiaTimerSecurityPanel();
+
+ setSecurityPanelVisible(true);
+ }
+ }
}
/**
@@ -616,10 +629,18 @@ public class OneToOneCallPeerPanel
public void setMute(boolean isMute)
{
if(isMute)
+ {
muteStatusLabel.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.MUTE_STATUS_ICON)));
+ muteStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 3, 2, 3));
+ }
else
+ {
muteStatusLabel.setIcon(null);
+ muteStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ }
this.revalidate();
this.repaint();
@@ -632,10 +653,18 @@ public class OneToOneCallPeerPanel
public void setOnHold(boolean isOnHold)
{
if(isOnHold)
+ {
holdStatusLabel.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.HOLD_STATUS_ICON)));
+ holdStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 3, 2, 3));
+ }
else
+ {
holdStatusLabel.setIcon(null);
+ holdStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ }
this.revalidate();
this.repaint();
@@ -650,43 +679,48 @@ public class OneToOneCallPeerPanel
*/
public void securityOn(CallPeerSecurityOnEvent evt)
{
- if((evt.getSecurityController().requiresSecureSignalingTransport()
- && callPeer.getProtocolProvider().isSignalingTransportSecure())
- || !evt.getSecurityController().requiresSecureSignalingTransport())
+ // If the securityOn is called without a specific event, we'll just set
+ // the security label status to on.
+ if (evt == null)
{
- securityImageID = ImageLoader.SECURE_BUTTON_ON;
- securityStatusLabel.setIcon(new ImageIcon(ImageLoader
- .getImage(securityImageID)));
+ securityStatusLabel.setSecurityOn();
+ return;
}
- //set common encryption properties
- securityStatusLabel.setEncryptionCipher(evt.getCipher());
- switch (evt.getSessionType())
+ SrtpControl srtpControl = evt.getSecurityController();
+
+ if ((srtpControl.requiresSecureSignalingTransport()
+ && callPeer.getProtocolProvider().isSignalingTransportSecure())
+ || !srtpControl.requiresSecureSignalingTransport())
{
- case CallPeerSecurityStatusEvent.AUDIO_SESSION:
- securityStatusLabel.setAudioSecurityOn(true);
- break;
- case CallPeerSecurityStatusEvent.VIDEO_SESSION:
- securityStatusLabel.setVideoSecurityOn(true);
- break;
+ if (srtpControl instanceof ZrtpControl)
+ {
+ securityStatusLabel.setText("zrtp");
+
+ if (!((ZrtpControl) srtpControl).isSecurityVerified())
+ securityStatusLabel.setSecurityPending();
+ else
+ securityStatusLabel.setSecurityOn();
+ }
+ else
+ securityStatusLabel.setSecurityOn();
}
- //set encryption specific options
- if (securityPanel == null)
+ // if we have some other panel, using other control
+ if(!srtpControl.getClass().isInstance(
+ securityPanel.getSecurityControl()))
{
- securityPanel = SecurityPanel.create(evt.getSecurityController());
-
- GridBagConstraints constraints = new GridBagConstraints();
+ setSecurityPanelVisible(false);
- constraints.fill = GridBagConstraints.NONE;
- constraints.gridx = 0;
- constraints.gridy = 2;
- constraints.weightx = 0;
- constraints.weighty = 0;
- constraints.insets = new Insets(5, 0, 0, 0);
- this.add(securityPanel, constraints);
+ securityPanel
+ = SecurityPanel.create(this, callPeer, srtpControl);
}
- securityPanel.refreshStates();
+
+ securityPanel.securityOn(evt);
+
+ if (srtpControl instanceof ZrtpControl
+ && !((ZrtpControl) srtpControl).isSecurityVerified())
+ setSecurityPanelVisible(true);
this.revalidate();
}
@@ -696,27 +730,21 @@ public class OneToOneCallPeerPanel
*/
public void securityOff(CallPeerSecurityOffEvent evt)
{
- securityImageID = ImageLoader.SECURE_BUTTON_OFF;
- securityStatusLabel.setIcon(new ImageIcon(ImageLoader
- .getImage(securityImageID)));
+ securityStatusLabel.setText("");
+ securityStatusLabel.setSecurityOff();
+ if (securityStatusLabel.getBorder() == null)
+ securityStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 5, 2, 3));
- switch (evt.getSessionType())
- {
- case CallPeerSecurityStatusEvent.AUDIO_SESSION:
- securityStatusLabel.setAudioSecurityOn(false);
- break;
- case CallPeerSecurityStatusEvent.VIDEO_SESSION:
- securityStatusLabel.setVideoSecurityOn(false);
- break;
- }
+ securityPanel.securityOff(evt);
+ }
- if (securityPanel != null
- && !securityStatusLabel.isAudioSecurityOn()
- && !securityStatusLabel.isVideoSecurityOn())
- {
- securityPanel.getParent().remove(securityPanel);
- securityPanel = null;
- }
+ /**
+ * Indicates that the security status is pending confirmation.
+ */
+ public void securityPending()
+ {
+ securityStatusLabel.setSecurityPending();
}
/**
@@ -726,7 +754,8 @@ public class OneToOneCallPeerPanel
*/
public void securityTimeout(CallPeerSecurityTimeoutEvent evt)
{
-
+ if (securityPanel != null)
+ securityPanel.securityTimeout(evt);
}
/**
@@ -763,6 +792,9 @@ public class OneToOneCallPeerPanel
public void printDTMFTone(char dtmfChar)
{
dtmfLabel.setText(dtmfLabel.getText() + dtmfChar);
+ if (dtmfLabel.getBorder() == null)
+ dtmfLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 1, 2, 5));
}
/**
@@ -1042,175 +1074,6 @@ public class OneToOneCallPeerPanel
}
/**
- * The Mouse listener for local video. It is responsible for dragging local
- * video.
- */
-// private class LocalVideoMouseListener
-// implements MouseListener,
-// MouseMotionListener
-// {
-// /**
-// * Indicates if we're currently during a drag operation.
-// */
-// private boolean inDrag = false;
-//
-// /**
-// * The previous x coordinate of the drag.
-// */
-// private int previousX = 0;
-//
-// /**
-// * The previous y coordinate of the drag.
-// */
-// private int previousY = 0;
-//
-// /**
-// * Indicates that the mouse has been dragged.
-// *
-// * @param event the <tt>MouseEvent</tt> that notified us
-// */
-// public void mouseDragged(MouseEvent event)
-// {
-// Point p = event.getPoint();
-//
-// if (inDrag)
-// {
-// Component c = (Component) event.getSource();
-//
-// int newX = c.getX() + p.x - previousX;
-// int newY = c.getY() + p.y - previousY;
-//
-// Component remoteContainer;
-// if (remoteVideo != null)
-// remoteContainer = remoteVideo;
-// else
-// synchronized (videoContainers)
-// {
-// // If there's no remote video we limit the drag to the
-// // parent video container.
-// if (videoContainers != null
-// && videoContainers.size() > 0)
-// remoteContainer = videoContainers.get(
-// videoContainers.size() - 1);
-// else
-// // In the case no video container is available
-// // we just limit the drag to this panel.
-// remoteContainer = OneToOneCallPeerPanel.this;
-// }
-//
-// int minX = remoteContainer.getX();
-// int maxX = remoteContainer.getX() + remoteContainer.getWidth();
-// int minY = remoteContainer.getY();
-// int maxY = remoteContainer.getY() + remoteContainer.getHeight();
-//
-// if (newX < minX)
-// newX = minX;
-//
-// if (newX + c.getWidth() > maxX)
-// newX = maxX - c.getWidth();
-//
-// if (newY < minY)
-// newY = minY;
-//
-// if (newY + c.getHeight() > maxY)
-// newY = maxY - c.getHeight();
-//
-// c.setLocation(newX, newY);
-// if (closeButton.isVisible())
-// closeButton.setVisible(false);
-// }
-// }
-//
-// public void mouseMoved(MouseEvent event) {}
-//
-// public void mouseClicked(MouseEvent event) {}
-//
-// public void mouseEntered(MouseEvent event) {}
-//
-// public void mouseExited(MouseEvent event) {}
-//
-// /**
-// * Indicates that the mouse has been pressed.
-// *
-// * @param event the <tt>MouseEvent</tt> that notified us
-// */
-// public void mousePressed(MouseEvent event)
-// {
-// Point p = event.getPoint();
-//
-// previousX = p.x;
-// previousY = p.y;
-// inDrag = true;
-// }
-//
-// /**
-// * Indicates that the mouse has been released.
-// *
-// * @param event the <tt>MouseEvent</tt> that notified us
-// */
-// public void mouseReleased(MouseEvent event)
-// {
-// inDrag = false;
-// previousX = 0;
-// previousY = 0;
-//
-// if (!closeButton.isVisible())
-// {
-// Component c = (Component) event.getSource();
-// closeButton.setLocation(
-// c.getX() + c.getWidth() - closeButton.getWidth() - 3,
-// c.getY() + 3);
-// closeButton.setVisible(true);
-// }
-// }
-// }
-
-// private class CloseButton
-// extends Label
-// implements MouseListener
-// {
-// private static final long serialVersionUID = 0L;
-//
-// Image image = ImageLoader.getImage(ImageLoader.CLOSE_VIDEO);
-//
-// public CloseButton()
-// {
-// int buttonWidth = image.getWidth(this) + 5;
-// int buttonHeight = image.getHeight(this) + 5;
-//
-// setPreferredSize(new Dimension(buttonWidth, buttonHeight));
-// setSize(new Dimension(buttonWidth, buttonHeight));
-//
-// this.addMouseListener(this);
-// }
-//
-// public void paint(Graphics g)
-// {
-// g.setColor(Color.GRAY);
-// g.fillRect(0, 0, getWidth(), getHeight());
-// g.drawImage(image,
-// getWidth()/2 - image.getWidth(this)/2,
-// getHeight()/2 - image.getHeight(this)/2, this);
-// }
-//
-// public void mouseClicked(MouseEvent event)
-// {
-// setLocalVideoVisible(false);
-//
-// callRenderer.getCallContainer()
-// .setShowHideVideoButtonSelected(false);
-// }
-//
-// public void mouseEntered(MouseEvent event) {}
-//
-// public void mouseExited(MouseEvent event) {}
-//
-// public void mousePressed(MouseEvent event) {}
-//
-// public void mouseReleased(MouseEvent event) {}
-// }
-
- /**
* Reloads all icons.
*/
public void loadSkin()
@@ -1254,63 +1117,6 @@ public class OneToOneCallPeerPanel
public void setLocalVideoVisible(boolean isVisible)
{
videoHandler.setLocalVideoVisible(isVisible);
-// synchronized (videoContainers)
-// {
-// this.localVideoVisible = isVisible;
-//
-// if (isVisible
-// != callRenderer.getCallContainer()
-// .isShowHideVideoButtonSelected())
-// {
-// callRenderer.getCallContainer()
-// .setShowHideVideoButtonSelected(isVisible);
-// }
-//
-// int videoContainerCount;
-//
-// if ((videoTelephony != null)
-// && ((videoContainerCount = videoContainers.size()) > 0))
-// {
-// Container videoContainer
-// = videoContainers.get(videoContainerCount - 1);
-//
-// if (localVideo != null)
-// {
-// if (isVisible)
-// {
-// Container localVideoParent = localVideo.getParent();
-//
-// if (localVideoParent != null)
-// localVideoParent.remove(localVideo);
-//
-// Container closeButtonParent
-// = closeButton.getParent();
-//
-// if (closeButtonParent != null)
-// closeButtonParent.remove(closeButton);
-//
-// videoContainer.add(localVideo, VideoLayout.LOCAL, 0);
-// videoContainer.add(
-// closeButton,
-// VideoLayout.CLOSE_LOCAL_BUTTON,
-// 0);
-// }
-// else
-// {
-// videoContainer.remove(localVideo);
-// videoContainer.remove(closeButton);
-// }
-//
-// /*
-// * Just like #handleVideoEvent(VideoEvent, Container) says,
-// * we have to be explicit in order to achieve a proper
-// * layout and an up-to-date painting.
-// */
-// videoContainer.validate();
-// videoContainer.repaint();
-// }
-// }
-// }
}
/**
@@ -1353,4 +1159,174 @@ public class OneToOneCallPeerPanel
{
return videoHandler;
}
+
+ /**
+ * Initializes the security status label, shown in the call status bar.
+ */
+ private void initSecurityStatusLabel()
+ {
+ securityStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 5, 2, 5));
+
+ securityStatusLabel.setSecurityOff();
+
+ securityStatusLabel.addMouseListener(new MouseAdapter()
+ {
+ /**
+ * Invoked when a mouse button has been pressed on a component.
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ // Only show the security details if the security is on.
+ if (callPeer.getCurrentSecuritySettings()
+ instanceof CallPeerSecurityOnEvent)
+ {
+ setSecurityPanelVisible(!callRenderer.getCallContainer()
+ .getCallWindow().getFrame().getGlassPane().isVisible());
+ }
+ }
+ });
+ }
+
+ /**
+ * Shows/hides the security panel.
+ *
+ * @param isVisible <tt>true</tt> to show the security panel, <tt>false</tt>
+ * to hide it
+ */
+ public void setSecurityPanelVisible(boolean isVisible)
+ {
+ final JFrame callFrame = callRenderer.getCallContainer()
+ .getCallWindow().getFrame();
+
+ final JPanel glassPane = (JPanel) callFrame.getGlassPane();
+
+ if (!isVisible)
+ {
+ // Need to hide the security panel explicitly in order to keep the
+ // fade effect.
+ securityPanel.setVisible(false);
+ glassPane.setVisible(false);
+ glassPane.removeAll();
+ }
+ else
+ {
+ glassPane.setLayout(null);
+ glassPane.addMouseListener(new MouseListener()
+ {
+ public void mouseReleased(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mousePressed(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mouseExited(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mouseEntered(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mouseClicked(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+ });
+
+ Point securityLabelPoint = securityStatusLabel.getLocation();
+
+ Point newPoint
+ = SwingUtilities.convertPoint(securityStatusLabel.getParent(),
+ securityLabelPoint.x, securityLabelPoint.y,
+ callFrame);
+
+ securityPanel.setBeginPoint(
+ new Point((int) newPoint.getX() + 15, 0));
+ securityPanel.setBounds(
+ 0, (int) newPoint.getY() - 5, callFrame.getWidth(), 110);
+
+ glassPane.add(securityPanel);
+ // Need to show the security panel explicitly in order to keep the
+ // fade effect.
+ securityPanel.setVisible(true);
+ glassPane.setVisible(true);
+
+ glassPane.addComponentListener(new ComponentAdapter()
+ {
+ /**
+ * Invoked when the component's size changes.
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ if (glassPane.isVisible())
+ {
+ glassPane.setVisible(false);
+ callFrame.removeComponentListener(this);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Re-dispatches glass pane mouse events only in case they occur on the
+ * security panel.
+ *
+ * @param glassPane the glass pane
+ * @param e the mouse event in question
+ */
+ private void redispatchMouseEvent(Component glassPane, MouseEvent e)
+ {
+ Point glassPanePoint = e.getPoint();
+
+ Point securityPanelPoint = SwingUtilities.convertPoint(
+ glassPane,
+ glassPanePoint,
+ securityPanel);
+
+ Component component;
+ Point componentPoint;
+
+ if (securityPanelPoint.y > 0)
+ {
+ component = securityPanel;
+ componentPoint = securityPanelPoint;
+ }
+ else
+ {
+ Container contentPane
+ = callRenderer.getCallContainer().getCallWindow()
+ .getFrame().getContentPane();
+
+ Point containerPoint = SwingUtilities.convertPoint(
+ glassPane,
+ glassPanePoint,
+ contentPane);
+
+ component = SwingUtilities.getDeepestComponentAt(contentPane,
+ containerPoint.x, containerPoint.y);
+
+ componentPoint = SwingUtilities.convertPoint(contentPane,
+ glassPanePoint, component);
+ }
+
+ if (component != null)
+ component.dispatchEvent(new MouseEvent( component,
+ e.getID(),
+ e.getWhen(),
+ e.getModifiers(),
+ componentPoint.x,
+ componentPoint.y,
+ e.getClickCount(),
+ e.isPopupTrigger()));
+
+ e.consume();
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/ParanoiaTimerSecurityPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/ParanoiaTimerSecurityPanel.java
new file mode 100644
index 0000000..3efee42
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/ParanoiaTimerSecurityPanel.java
@@ -0,0 +1,142 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.main.call;
+
+import net.java.sip.communicator.impl.gui.*;
+import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+
+import javax.swing.*;
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.util.Timer;
+
+/**
+ * @author Damian Minkov
+ * @author Yana Stamcheva
+ */
+public class ParanoiaTimerSecurityPanel
+ extends SecurityPanel<SrtpControl>
+{
+ /**
+ * The security timer.
+ */
+ private Timer timer = new Timer(true);
+
+ /**
+ * Creates an instance of this <tt>ParanoiaTimerSecurityPanel</tt>.
+ */
+ ParanoiaTimerSecurityPanel()
+ {
+ super(null);
+
+ initComponents();
+ }
+
+ /**
+ * Initializes contained components.
+ */
+ private void initComponents()
+ {
+ final SimpleDateFormat format = new SimpleDateFormat("mm:ss");
+ final Calendar c = Calendar.getInstance();
+ final JLabel counter = new JLabel();
+
+ counter.setForeground(Color.red);
+ counter.setFont(counter.getFont().deriveFont(
+ (float)(counter.getFont().getSize() + 5)));
+
+ setLayout(new GridBagLayout());
+ setBorder(
+ BorderFactory.createEmptyBorder(20, 20, 20, 20));
+
+ GridBagConstraints constraints = new GridBagConstraints();
+
+ JLabel messageLabel = new JLabel(GuiActivator.getResources()
+ .getI18NString("service.gui.security.SECURITY_ALERT"));
+
+ messageLabel.setForeground(Color.WHITE);
+
+ constraints.anchor = GridBagConstraints.CENTER;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 0;
+ constraints.gridy = 0;
+ add(messageLabel, constraints);
+
+ constraints.anchor = GridBagConstraints.CENTER;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 0;
+ constraints.gridy = 1;
+ add(counter, constraints);
+
+ ZrtpControl zrtpControl = null;
+ if (securityControl instanceof ZrtpControl)
+ zrtpControl = (ZrtpControl) securityControl;
+
+ int initialSeconds = 0;
+
+ if (zrtpControl != null)
+ initialSeconds = (int) zrtpControl.getTimeoutValue()/1000;
+
+ c.set(Calendar.HOUR, 0);
+ c.set(Calendar.MINUTE, 0);
+ c.set(Calendar.SECOND, initialSeconds);
+
+ counter.setText(format.format(c.getTime()));
+
+ if (initialSeconds > 0)
+ timer.schedule(new TimerTask()
+ {
+ @Override
+ public void run()
+ {
+ c.add(Calendar.SECOND, -1);
+ counter.setText(format.format(c.getTime()));
+ }
+ }, 0, 1000);
+ }
+
+ /**
+ * Cancels the security timer.
+ *
+ * @param evt the security event of which we're notified
+ */
+ public void securityOn(CallPeerSecurityOnEvent evt)
+ {
+ timer.cancel();
+ }
+
+ /**
+ * Nothing to do here.
+ *
+ * @param evt the security event of which we're notified
+ */
+ public void securityOff(CallPeerSecurityOffEvent evt) {}
+
+ /**
+ * Indicates that the security is time-outed, is not supported by the
+ * other end.
+ * @param evt Details about the event that caused this message.
+ */
+ public void securityTimeout(CallPeerSecurityTimeoutEvent evt)
+ {
+ timer.cancel();
+
+ // fail peer, call
+ if(evt.getSource() instanceof AbstractCallPeer)
+ {
+ AbstractCallPeer peer = (AbstractCallPeer)evt.getSource();
+ peer.setState(CallPeerState.FAILED, "Encryption Required!");
+ }
+ }
+
+ public void loadSkin()
+ {
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java
index 32ca281..202c150 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java
@@ -7,6 +7,8 @@
package net.java.sip.communicator.impl.gui.main.call;
import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.skin.*;
import net.java.sip.communicator.util.swing.*;
@@ -15,11 +17,43 @@ import net.java.sip.communicator.util.swing.*;
*
* @author Ingo Bauersachs
*/
-public abstract class SecurityPanel
- extends TransparentPanel
+public abstract class SecurityPanel<T extends SrtpControl>
+ extends FadeInBalloonPanel
implements Skinnable
{
/**
+ * The currently used security control.
+ */
+ protected T securityControl;
+
+ /**
+ * Create security panel using the security control.
+ * @param securityControl
+ */
+ public SecurityPanel(T securityControl)
+ {
+ this.securityControl = securityControl;
+ }
+
+ /**
+ * The currently used security control.
+ * @return
+ */
+ public T getSecurityControl()
+ {
+ return securityControl;
+ }
+
+ /**
+ * The currently used security control.
+ * @return
+ */
+ public void setSecurityControl(T securityControl)
+ {
+ this.securityControl = securityControl;
+ }
+
+ /**
* Creates the security panel depending on the concrete implementation of
* the passed security controller.
*
@@ -29,23 +63,49 @@ public abstract class SecurityPanel
* controller or an {@link TransparentPanel} if the controller is
* unknown or does not have any controls to show.
*/
- public static SecurityPanel create(SrtpControl srtpControl)
+ public static SecurityPanel create( CallPeerRenderer peerRenderer,
+ CallPeer callPeer,
+ SrtpControl srtpControl)
{
if(srtpControl instanceof ZrtpControl)
- return new ZrtpSecurityPanel((ZrtpControl)srtpControl);
+ return new ZrtpSecurityPanel( peerRenderer,
+ callPeer,
+ (ZrtpControl)srtpControl);
- return new SecurityPanel()
+ return new SecurityPanel<SrtpControl>(srtpControl)
{
public void loadSkin()
{}
- public void refreshStates()
+
+ public void securityOn(CallPeerSecurityOnEvent evt)
+ {}
+
+ public void securityOff(CallPeerSecurityOffEvent evt)
+ {}
+
+ public void securityTimeout(CallPeerSecurityTimeoutEvent evt)
{}
};
}
/**
- * Forces the panel to update the security information presented to the
- * user.
+ * Indicates that the security is turned on.
+ *
+ * @param evt details about the event that caused this message.
+ */
+ public abstract void securityOn(CallPeerSecurityOnEvent evt);
+
+ /**
+ * Indicates that the security is turned off.
+ *
+ * @param evt details about the event that caused this message.
+ */
+ public abstract void securityOff(CallPeerSecurityOffEvent evt);
+
+ /**
+ * Indicates that the security is timeouted, is not supported by the
+ * other end.
+ * @param evt Details about the event that caused this message.
*/
- public abstract void refreshStates();
+ public abstract void securityTimeout(CallPeerSecurityTimeoutEvent evt);
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java b/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java
index bfe2ada..994808f 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java
@@ -10,8 +10,10 @@ import java.awt.*;
import javax.swing.*;
+import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.util.skin.*;
+import net.java.sip.communicator.util.swing.*;
/**
* The <tt>SecurityStatusLabel</tt> is meant to be used to visualize the audio
@@ -22,7 +24,7 @@ import net.java.sip.communicator.util.skin.*;
*/
public class SecurityStatusLabel
extends JLabel
- implements Skinnable
+ implements Skinnable
{
/**
* Serial version UID.
@@ -30,157 +32,135 @@ public class SecurityStatusLabel
private static final long serialVersionUID = 0L;
/**
- * Indicates the state of the audio security (on or off).
+ * The icon used for the not secured state.
*/
- private boolean isAudioSecurityOn = false;
+ private static Icon securityOffIcon;
/**
- * Indicates the state of the video security (on or off).
+ * The icon used for the secured state.
*/
- private boolean isVideoSecurityOn = false;
+ private static Icon securityOnIcon;
/**
- * The encryption cipher.
+ * The background used to indicate that the call is secured.
*/
- private String encryptionCipher;
+ private final static Color securityOnBackground
+ = new Color(GuiActivator.getResources()
+ .getColor("service.gui.SECURITY_ON"));
/**
- * The default security status icon.
+ * The background used to indicate that the call is not secured.
*/
- private final Icon defaultIcon;
+ private final static Color securityOffBackground
+ = new Color(GuiActivator.getResources()
+ .getColor("service.gui.SECURITY_OFF"));
/**
- * The parent window, where this component will be contained.
+ * The background used to indicate that the call is not secured.
*/
- private final Window parentWindow;
+ private final static Color goingSecureBackground
+ = new Color(GuiActivator.getResources()
+ .getColor("service.gui.GOING_SECURE"));
+
+ /**
+ * Indicates security status.
+ */
+ private boolean isSecure = false;
/**
* Creates an instance of <tt>SecurityStatusLabel</tt> by specifying the
* <tt>GuiCallPeer</tt>, the icon and the alignment to use for the label.
*/
- public SecurityStatusLabel(Window parentWindow, Icon securityIcon)
+ public SecurityStatusLabel()
{
- this.parentWindow = parentWindow;
- this.defaultIcon = securityIcon;
-
loadSkin();
- this.setHorizontalAlignment(JLabel.CENTER);
+ setBorder(BorderFactory.createEmptyBorder(2, 8, 2, 3));
+ setForeground(Color.WHITE);
- this.setToolTipText("Security status");
+ setHorizontalAlignment(JLabel.CENTER);
+ setHorizontalTextPosition(JLabel.LEFT);
}
/**
- * Create an extended tooltip showing some more security details.
- * @return the created tooltip
+ * Paints a custom background to better indicate security state.
+ *
+ * @param g the <tt>Graphics</tt> object
*/
- public JToolTip createToolTip()
+ public void paintComponent(Graphics g)
{
- ExtendedTooltip tip = new ExtendedTooltip(parentWindow, true);
+ g = g.create();
- tip.setTitle("Security status");
-
- ImageIcon audioStatusIcon;
- String audioStatusString;
- if (isAudioSecurityOn)
- {
- audioStatusIcon = new ImageIcon(
- ImageLoader.getImage(ImageLoader.SECURE_AUDIO_ON));
- audioStatusString = "Audio security on.";
- }
- else
+ try
{
- audioStatusIcon = new ImageIcon(
- ImageLoader.getImage(ImageLoader.SECURE_AUDIO_OFF));
- audioStatusString = "Audio security off.";
+ AntialiasingManager.activateAntialiasing(g);
+ g.setColor(getBackground());
+
+ if (getIcon() != null)
+ {
+ if (isSecure)
+ g.fillRoundRect(
+ 0, 0, this.getWidth(), this.getHeight(), 20, 20);
+ else
+ g.fillRoundRect(
+ 0, 0, this.getWidth(), this.getHeight(), 20, 20);
+ }
+
+ g.setColor(getForeground());
+
+ super.paintComponent(g);
}
-
- ImageIcon videoStatusIcon;
- String videoStatusString;
- if (isVideoSecurityOn)
+ finally
{
- videoStatusIcon = new ImageIcon(
- ImageLoader.getImage(ImageLoader.SECURE_VIDEO_ON));
- videoStatusString = "Video security on.";
+ g.dispose();
}
- else
- {
- videoStatusIcon = new ImageIcon(
- ImageLoader.getImage(ImageLoader.SECURE_VIDEO_OFF));
- videoStatusString = "Video security off.";
- }
-
- String cipher = "Cipher: " + encryptionCipher;
-
- tip.addLine(audioStatusIcon,
- audioStatusString);
-
- tip.addLine(videoStatusIcon,
- videoStatusString);
-
- tip.addLine(null, cipher);
-
- tip.setComponent(this);
-
- return tip;
- }
-
- /**
- * Gets the audio security status.
- * @return the audio security status.
- */
- public boolean isAudioSecurityOn()
- {
- return isAudioSecurityOn;
}
/**
* Sets the audio security on or off.
- *
- * @param isAudioSecurityOn indicates if the audio security is turned on or
- * off.
- */
- public void setAudioSecurityOn(boolean isAudioSecurityOn)
- {
- this.isAudioSecurityOn = isAudioSecurityOn;
- }
-
- /**
- * Gets the video security status.
- * @return the video security status.
*/
- public boolean isVideoSecurityOn()
+ public void setSecurityOn()
{
- return isVideoSecurityOn;
+ isSecure = true;
+ setIcon(securityOnIcon);
+ setBackground(securityOnBackground);
+ setToolTipText(GuiActivator.getResources().getI18NString(
+ "service.gui.security.CALL_SECURED_TOOLTIP"));
}
/**
- * Sets the video security on or off.
- *
- * @param isVideoSecurityOn indicates if the video security is turned on or
- * off.
+ * Sets the audio security on or off.
*/
- public void setVideoSecurityOn(boolean isVideoSecurityOn)
+ public void setSecurityOff()
{
- this.isVideoSecurityOn = isVideoSecurityOn;
+ isSecure = false;
+ setIcon(securityOffIcon);
+ setBackground(securityOffBackground);
+ this.setToolTipText(GuiActivator.getResources().getI18NString(
+ "service.gui.security.CALL_NOT_SECURED_TOOLTIP"));
}
/**
- * Sets the cipher used for the encryption of the current call.
- *
- * @param encryptionCipher the cipher used for the encryption of the
- * current call.
+ * Sets the audio security on or off.
*/
- public void setEncryptionCipher(String encryptionCipher)
+ public void setSecurityPending()
{
- this.encryptionCipher = encryptionCipher;
+ isSecure = false;
+ setIcon(securityOnIcon);
+ setBackground(goingSecureBackground);
+ this.setToolTipText(GuiActivator.getResources().getI18NString(
+ "service.gui.security.CALL_SECURED_COMPARE_TOOLTIP"));
}
/**
- * Reloads icon.
+ * Reloads icons.
*/
public void loadSkin()
{
- this.setIcon(defaultIcon);
+ securityOffIcon = new ImageIcon(ImageLoader
+ .getImage(ImageLoader.SECURE_BUTTON_OFF));
+
+ securityOnIcon = new ImageIcon(ImageLoader
+ .getImage(ImageLoader.SECURE_BUTTON_ON));
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/ZrtpSecurityPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/ZrtpSecurityPanel.java
index 547e796..73cfa37 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/ZrtpSecurityPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/ZrtpSecurityPanel.java
@@ -8,12 +8,17 @@ package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.awt.event.*;
+import java.beans.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.service.protocol.media.*;
+import net.java.sip.communicator.util.event.*;
import net.java.sip.communicator.util.swing.*;
/**
@@ -24,102 +29,580 @@ import net.java.sip.communicator.util.swing.*;
* @author Yana Stamcheva
*/
public class ZrtpSecurityPanel
- extends SecurityPanel
+ extends SecurityPanel<ZrtpControl>
+ implements VideoListener,
+ PropertyChangeListener
{
- private SIPCommButton sasVerificationButton;
- private Image iconEncr;
- private Image iconEncrVerified;
- private final JLabel securityStringLabel = new JLabel();
+ /**
+ * The icon indicating that the short authentication string has been
+ * verified.
+ */
+ private static Icon encryptionVerifiedIcon;
+
+ /**
+ * The icon indicating that the audio is secure.
+ */
+ private static Icon audioSecuredIcon;
+
+ /**
+ * The icon indicating that the audio is not secure.
+ */
+ private static Icon audioNotSecuredIcon;
+
+ /**
+ * The icon indicating that the video is secure.
+ */
+ private static Icon videoSecuredIcon;
+
+ /**
+ * The icon indicating that the video is not secure.
+ */
+ private static Icon videoNotSecuredIcon;
+
+ /**
+ * The label showing the security authentication string.
+ */
+ private final JLabel securityStringLabel = createSecurityLabel("", null);
+
+ /**
+ * The label showing audio security status.
+ */
+ private final JLabel audioSecurityLabel;
+
+ /**
+ * The label showing video security status.
+ */
+ private final JLabel videoSecurityLabel;
+
+ /**
+ * The button, which closes this panel.
+ */
+ private final JButton closeButton
+ = new SIPCommButton(ImageLoader.getImage(ImageLoader.CLOSE_VIDEO));
+
+ /**
+ * The label containing information about the security authentication
+ * string.
+ */
+ private final JLabel compareLabel = createSecurityLabel("", null);
+
+ /**
+ * The button confirming the security authentication string.
+ */
+ private final JButton confirmButton = new JButton("");
+
+ /**
+ * The label showing the cipher.
+ */
+ private JLabel cipherLabel;
+
+ /**
+ * Indicates if the security authentication string has been verified.
+ */
private boolean sasVerified = false;
- private final ZrtpControl zrtpControl;
+ /**
+ * Indicates the state of the audio security (on or off).
+ */
+ private boolean isAudioSecurityOn = false;
+
+ /**
+ * Indicates the state of the video security (on or off).
+ */
+ private boolean isVideoSecurityOn = false;
+
+ /**
+ * The encryption cipher.
+ */
+ private String encryptionCipher;
+
+ /**
+ * The corresponding call peer.
+ */
+ private final CallPeer callPeer;
+ /**
+ * The renderer of the corresponding call peer.
+ */
+ private final CallPeerRenderer peerRenderer;
/**
* Creates an instance of <tt>SecurityPanel</tt> by specifying the
* corresponding <tt>peer</tt>.
- *
+ *
+ * @param peerRenderer the parent renderer
+ * @param callPeer the peer, which security this panel is about
* @param zrtpControl the ZRTP security controller that provides information
* for this panel and receives the user input
*/
- public ZrtpSecurityPanel(ZrtpControl zrtpControl)
+ public ZrtpSecurityPanel( CallPeerRenderer peerRenderer,
+ CallPeer callPeer,
+ ZrtpControl zrtpControl)
{
- this.zrtpControl = zrtpControl;
+ super(zrtpControl);
- this.setBorder(null);
- this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0));
+ this.peerRenderer = peerRenderer;
+ this.callPeer = callPeer;
- this.setToolTipText(GuiActivator.getResources().getI18NString(
- "service.gui.COMPARE_WITH_PARTNER"));
+ OperationSetVideoTelephony telephony
+ = callPeer.getProtocolProvider()
+ .getOperationSet(OperationSetVideoTelephony.class);
+
+ telephony.addVideoListener(callPeer, this);
+ telephony.addPropertyChangeListener(callPeer.getCall(), this);
+
+ audioSecurityLabel = createSecurityLabel("", null);
+
+ videoSecurityLabel = createSecurityLabel("", null);
loadSkin();
}
/**
- * Adds security related components to this panel.
+ * Adds all components.
*/
- private void addComponentsToPane()
+ private void addComponents()
{
- this.add(sasVerificationButton);
- this.add(securityStringLabel);
+ setAudioSecurityOn(isAudioSecurityOn);
+ setVideoSecurityOn(isVideoSecurityOn);
- securityStringLabel
- .setFont(securityStringLabel.getFont().deriveFont(14f));
+ closeButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ peerRenderer.setSecurityPanelVisible(false);
+ }
+ });
+
+ setLayout(new GridBagLayout());
+ GridBagConstraints constraints = new GridBagConstraints();
- // Action to trigger SAS verification
- sasVerificationButton.addActionListener(new ActionListener()
+ constraints.anchor = GridBagConstraints.NORTHEAST;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 0;
+ constraints.gridy = 0;
+ constraints.gridheight = 1;
+ constraints.weightx = 0f;
+ constraints.weighty = 0f;
+ this.add(audioSecurityLabel, constraints);
+
+ constraints.anchor = GridBagConstraints.NORTHEAST;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 0;
+ constraints.gridy = 1;
+ constraints.gridheight = 1;
+ constraints.weightx = 0f;
+ constraints.weighty = 0f;
+ constraints.insets = new Insets(5, 0, 0, 0);
+ this.add(videoSecurityLabel, constraints);
+
+ String cipher = "";
+ if (encryptionCipher != null && encryptionCipher.length() > 0)
+ {
+ cipher = GuiActivator.getResources().getI18NString(
+ "service.gui.CIPHER", new String[]{encryptionCipher});
+ }
+
+ cipherLabel = createSecurityLabel(cipher, null);
+
+ constraints.anchor = GridBagConstraints.NORTHEAST;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 0;
+ constraints.gridy = 2;
+ constraints.gridheight = 1;
+ constraints.weightx = 0f;
+ constraints.weighty = 0f;
+ constraints.insets = new Insets(5, 0, 0, 0);
+ this.add(cipherLabel, constraints);
+
+ constraints.anchor = GridBagConstraints.NORTHWEST;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 1;
+ constraints.gridy = 0;
+ constraints.gridheight = 3;
+ constraints.weightx = 1f;
+ constraints.weighty = 0f;
+ constraints.insets = new Insets(0, 5, 0, 5);
+ this.add(createSasPanel(), constraints);
+
+ constraints.anchor = GridBagConstraints.NORTHEAST;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 2;
+ constraints.gridy = 0;
+ constraints.gridheight = 1;
+ constraints.weightx = 0f;
+ constraints.weighty = 0f;
+ constraints.insets = new Insets(0, 0, 0, 5);
+ this.add(closeButton, constraints);
+ }
+
+ /**
+ * Creates a security panel label.
+ *
+ * @param text the text of the label
+ * @param icon the label icon
+ * @return the created JLabel
+ */
+ private JLabel createSecurityLabel(String text, Icon icon)
+ {
+ JLabel label = new JLabel(text, icon, JLabel.LEFT);
+ label.setForeground(Color.WHITE);
+
+ return label;
+ }
+
+ /**
+ * Creates the ZRTP sas panel.
+ *
+ * @return the created ZRTP SAS panel
+ */
+ private JPanel createSasPanel()
+ {
+ sasVerified = getSecurityControl().isSecurityVerified();
+
+ TransparentPanel sasPanel = new TransparentPanel()
+ {
+ public void paintComponent(Graphics g)
+ {
+ g = g.create();
+ try
+ {
+ AntialiasingManager.activateAntialiasing(g);
+ g.setColor(new Color(1f, 1f, 1f, 0.1f));
+ g.fillRoundRect(
+ 0, 0, this.getWidth(), this.getHeight(), 10, 10);
+ g.setColor(Color.WHITE);
+ g.drawRoundRect(
+ 0, 0,
+ this.getWidth() - 1, this.getHeight() - 1,
+ 10, 10);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ };
+
+ sasPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ sasPanel.setPreferredSize(new Dimension(200, 80));
+ sasPanel.setMinimumSize(new Dimension(200, 80));
+ sasPanel.setMaximumSize(new Dimension(200, 80));
+ sasPanel.setLayout(new BoxLayout(sasPanel, BoxLayout.Y_AXIS));
+
+ initSasLabels();
+
+ SIPCommButton infoButton = new SIPCommButton(
+ ImageLoader.getImage(ImageLoader.CALL_INFO));
+ infoButton.setToolTipText(GuiActivator.getResources()
+ .getI18NString("service.gui.security.SAS_INFO_TOOLTIP"));
+
+ compareLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ JPanel stringPanel = new TransparentPanel(
+ new FlowLayout(FlowLayout.CENTER, 5, 0));
+ stringPanel.add(compareLabel);
+ stringPanel.add(infoButton);
+
+ sasPanel.add(stringPanel);
+
+ securityStringLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ sasPanel.add(securityStringLabel);
+
+ confirmButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
- sasVerified = !sasVerified;
- zrtpControl.setSASVerification(sasVerified);
+ if (getSecurityControl() != null)
+ {
+ getSecurityControl().setSASVerification(!sasVerified);
+
+ sasVerified = !sasVerified;
+ securityStringLabel
+ .setIcon(sasVerified ? encryptionVerifiedIcon : null);
+
+ if (sasVerified)
+ peerRenderer.securityOn(null);
+ else
+ peerRenderer.securityPending();
- if (sasVerified)
- sasVerificationButton.setImage(iconEncrVerified);
- else
- sasVerificationButton.setImage(iconEncr);
+ initSasLabels();
+ }
}
});
+ confirmButton.setAlignmentX(Component.CENTER_ALIGNMENT);
+ sasPanel.add(confirmButton);
+
+ return sasPanel;
+ }
+
+ /**
+ * Initializes security authentication string labels depending on the
+ * security verification status.
+ */
+ private void initSasLabels()
+ {
+ if (!sasVerified)
+ {
+ compareLabel.setText(GuiActivator.getResources().getI18NString(
+ "service.gui.security.COMPARE_WITH_PARTNER_SHORT"));
+ confirmButton.setText(GuiActivator.getResources()
+ .getI18NString("servoce.gui.CONFIRM"));
+ }
+ else
+ {
+ compareLabel.setText(GuiActivator.getResources().getI18NString(
+ "service.gui.security.STRING_COMPARED"));
+ confirmButton.setText(GuiActivator.getResources()
+ .getI18NString("servoce.gui.CLEAR"));
+ }
+
+ if (compareLabel.isVisible())
+ {
+ compareLabel.revalidate();
+ compareLabel.repaint();
+
+ confirmButton.revalidate();
+ confirmButton.repaint();
+ }
}
/**
* Refreshes the state of the SAS and the SAS verified padlock.
+ *
+ * @param evt the security event of which we're notified
*/
- public void refreshStates()
+ public void securityOn(CallPeerSecurityOnEvent evt)
{
- String securityString = zrtpControl.getSecurityString();
+ encryptionCipher = evt.getCipher();
+
+ if (encryptionCipher != null)
+ cipherLabel.setText(GuiActivator.getResources().getI18NString(
+ "service.gui.security.CIPHER", new String[]{encryptionCipher}));
+
+ switch (evt.getSessionType())
+ {
+ case CallPeerSecurityStatusEvent.AUDIO_SESSION:
+ setAudioSecurityOn(true);
+ break;
+ case CallPeerSecurityStatusEvent.VIDEO_SESSION:
+ setVideoSecurityOn(true);
+ break;
+ }
+
+ String securityString = getSecurityControl().getSecurityString();
if (securityString != null)
{
- securityStringLabel.setText(
- GuiActivator.getResources().getI18NString(
- "service.gui.COMPARE_WITH_PARTNER_SHORT",
- new String[] {securityString}
- )
- );
+ securityStringLabel.setText(securityString);
}
else
{
securityStringLabel.setText(null);
}
- sasVerified = zrtpControl.isSecurityVerified();
- sasVerificationButton
- .setImage(sasVerified ? iconEncrVerified : iconEncr);
+ sasVerified = getSecurityControl().isSecurityVerified();
+ securityStringLabel
+ .setIcon(sasVerified ? encryptionVerifiedIcon : null);
+
+ revalidate();
+ repaint();
+ }
+
+ /**
+ * Indicates that the security has gone off.
+ */
+ public void securityOff(CallPeerSecurityOffEvent evt)
+ {
+ switch (evt.getSessionType())
+ {
+ case CallPeerSecurityStatusEvent.AUDIO_SESSION:
+ setAudioSecurityOn(false);
+ break;
+ case CallPeerSecurityStatusEvent.VIDEO_SESSION:
+ setVideoSecurityOn(false);
+ break;
+ }
revalidate();
repaint();
}
+ public void securityTimeout(CallPeerSecurityTimeoutEvent evt)
+ {
+
+ }
+
/**
* Reloads icons and components.
*/
public void loadSkin()
{
- this.removeAll();
- iconEncrVerified = ImageLoader.getImage(ImageLoader.ENCR_VERIFIED);
- iconEncr = ImageLoader.getImage(ImageLoader.ENCR);
- sasVerificationButton = new SIPCommButton(iconEncr);
+ removeAll();
+
+ encryptionVerifiedIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.ENCR_VERIFIED));
+
+ audioSecuredIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_AUDIO_ON));
+
+ audioNotSecuredIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_AUDIO_OFF));
+
+ videoSecuredIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_VIDEO_ON));
+
+ videoNotSecuredIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_VIDEO_OFF));
+
+ addComponents();
+
+ if (isVisible())
+ {
+ revalidate();
+ repaint();
+ }
+ }
+
+ /**
+ * Updates audio security related components, depending on the given audio
+ * security state.
+ *
+ * @param isAudioSecurityOn indicates if the audio is secured or not
+ */
+ private void setAudioSecurityOn(final boolean isAudioSecurityOn)
+ {
+ if (!SwingUtilities.isEventDispatchThread())
+ {
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ setAudioSecurityOn(isAudioSecurityOn);
+ }
+ });
+ return;
+ }
+
+ Icon statusIcon;
+ String statusText;
+
+ this.isAudioSecurityOn = isAudioSecurityOn;
+
+ if (isAudioSecurityOn)
+ {
+ statusIcon = audioSecuredIcon;
+ statusText = GuiActivator.getResources()
+ .getI18NString("service.gui.security.SECURE_AUDIO");
+ }
+ else
+ {
+ statusIcon = audioNotSecuredIcon;
+ statusText = GuiActivator.getResources()
+ .getI18NString("service.gui.security.AUDIO_NOT_SECURED");
+ }
- this.addComponentsToPane();
+ audioSecurityLabel.setIcon(statusIcon);
+ audioSecurityLabel.setText(statusText);
+ }
+
+ /**
+ * Updates video security related components, depending on the given video
+ * security state.
+ *
+ * @param isVideoSecurityOn indicates if the video is secured or not
+ */
+ private void setVideoSecurityOn(final boolean isVideoSecurityOn)
+ {
+ if (!SwingUtilities.isEventDispatchThread())
+ {
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ setVideoSecurityOn(isVideoSecurityOn);
+ }
+ });
+ return;
+ }
+
+ this.isVideoSecurityOn = isVideoSecurityOn;
+
+ Icon statusIcon = null;
+ String statusText = null;
+
+ final OperationSetVideoTelephony telephony
+ = callPeer.getProtocolProvider()
+ .getOperationSet(OperationSetVideoTelephony.class);
+
+ if (telephony != null
+ && ((telephony.getVisualComponents(callPeer) != null
+ && telephony.getVisualComponents(callPeer).size() > 0)
+ || ((MediaAwareCallPeer<?, ?, ?>) callPeer)
+ .isLocalVideoStreaming()))
+ {
+ if (isVideoSecurityOn)
+ {
+ statusIcon = videoSecuredIcon;
+ statusText = GuiActivator.getResources()
+ .getI18NString("service.gui.security.SECURE_VIDEO");
+ }
+ else
+ {
+ statusIcon = videoNotSecuredIcon;
+ statusText = GuiActivator.getResources()
+ .getI18NString("service.gui.security.VIDEO_NOT_SECURED");
+ }
+ }
+ else
+ {
+ videoSecurityLabel.setVisible(false);
+ }
+
+ if (statusIcon != null && statusText != null)
+ {
+ videoSecurityLabel.setIcon(statusIcon);
+ videoSecurityLabel.setText(statusText);
+
+ if (!videoSecurityLabel.isVisible())
+ videoSecurityLabel.setVisible(true);
+ }
+
+ revalidate();
+ repaint();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void propertyChange(final PropertyChangeEvent event)
+ {
+ if (OperationSetVideoTelephony.LOCAL_VIDEO_STREAMING
+ .equals(event.getPropertyName()))
+ {
+ setVideoSecurityOn(isAudioSecurityOn);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void videoAdded(VideoEvent event)
+ {
+ setVideoSecurityOn(isAudioSecurityOn);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void videoRemoved(VideoEvent event)
+ {
+ setVideoSecurityOn(isAudioSecurityOn);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void videoUpdate(VideoEvent event)
+ {
+ setVideoSecurityOn(isAudioSecurityOn);
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java
index 00692b1..5e0568d 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java
@@ -13,6 +13,7 @@ import javax.swing.text.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
@@ -161,10 +162,8 @@ public abstract class BasicConferenceParticipantPanel
SoundLevelChangeEvent.MIN_LEVEL,
SoundLevelChangeEvent.MAX_LEVEL);
- securityStatusLabel = new SecurityStatusLabel(
- renderer.getCallContainer().getCallWindow().getFrame(),
- new ImageIcon(
- ImageLoader.getImage(ImageLoader.SECURE_OFF_CONF_CALL)));
+ securityStatusLabel = new SecurityStatusLabel();
+ securityStatusLabel.setSecurityOff();
this.setLayout(new GridBagLayout());
this.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7));
@@ -270,6 +269,8 @@ public abstract class BasicConferenceParticipantPanel
{
statusBarConstraints.gridx = statusBarConstraints.gridx + 1;
statusBarConstraints.weightx = 0f;
+ statusBarConstraints.insets = new Insets(0, 5, 0, 5);
+
this.statusBar.add(component, statusBarConstraints);
}
@@ -439,25 +440,32 @@ public abstract class BasicConferenceParticipantPanel
*/
public void securityOn(CallPeerSecurityOnEvent evt)
{
- if ((evt.getSecurityController().requiresSecureSignalingTransport()
- && renderer.getCall().getProtocolProvider()
- .isSignalingTransportSecure())
- || !evt.getSecurityController().requiresSecureSignalingTransport())
+ // If the securityOn is called without a specific event, we'll just set
+ // the security label status to on.
+ if (evt == null)
{
- securityImageID = ImageLoader.SECURE_ON_CONF_CALL;
- securityStatusLabel.setIcon(new ImageIcon(ImageLoader
- .getImage(securityImageID)));
+ securityStatusLabel.setSecurityOn();
+ return;
}
- securityStatusLabel.setEncryptionCipher(evt.getCipher());
- switch (evt.getSessionType())
+ SrtpControl srtpControl = evt.getSecurityController();
+
+ if ((srtpControl.requiresSecureSignalingTransport()
+ && renderer.getCall().getProtocolProvider()
+ .isSignalingTransportSecure())
+ || !srtpControl.requiresSecureSignalingTransport())
{
- case CallPeerSecurityStatusEvent.AUDIO_SESSION:
- securityStatusLabel.setAudioSecurityOn(true);
- break;
- case CallPeerSecurityStatusEvent.VIDEO_SESSION:
- securityStatusLabel.setVideoSecurityOn(true);
- break;
+ if (srtpControl instanceof ZrtpControl)
+ {
+ securityStatusLabel.setText("zrtp");
+
+ if (!((ZrtpControl) srtpControl).isSecurityVerified())
+ securityStatusLabel.setSecurityPending();
+ else
+ securityStatusLabel.setSecurityOn();
+ }
+ else
+ securityStatusLabel.setSecurityOn();
}
}
@@ -468,19 +476,18 @@ public abstract class BasicConferenceParticipantPanel
*/
public void securityOff(CallPeerSecurityOffEvent evt)
{
- securityImageID = ImageLoader.SECURE_OFF_CONF_CALL;
- securityStatusLabel.setIcon(new ImageIcon(ImageLoader
- .getImage(securityImageID)));
+ securityStatusLabel.setText("");
+ securityStatusLabel.setSecurityOff();
+ if (securityStatusLabel.getBorder() == null)
+ securityStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 5, 2, 3));
+ }
- securityStatusLabel.setEncryptionCipher(null);
- switch (evt.getSessionType())
- {
- case CallPeerSecurityStatusEvent.AUDIO_SESSION:
- securityStatusLabel.setAudioSecurityOn(false);
- break;
- case CallPeerSecurityStatusEvent.VIDEO_SESSION:
- securityStatusLabel.setVideoSecurityOn(false);
- break;
- }
+ /**
+ * Indicates that the security status is pending confirmation.
+ */
+ public void securityPending()
+ {
+ securityStatusLabel.setSecurityPending();
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java
index 951df44..f45eb58 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java
@@ -276,9 +276,9 @@ public class ConferenceFocusPanel
*
* @param state the state of the contained call peer
*/
- public void setPeerState(String state)
+ public void setPeerState(CallPeerState peerState, String state)
{
- focusPeerPanel.setPeerState(state);
+ focusPeerPanel.setPeerState(peerState, state);
}
/**
@@ -321,6 +321,7 @@ public class ConferenceFocusPanel
public void securityOn(CallPeerSecurityOnEvent evt)
{
focusPeerPanel.securityOn(evt);
+
for (ConferenceMemberPanel member : conferenceMembersPanels.values())
{
member.securityOn(evt);
@@ -342,6 +343,14 @@ public class ConferenceFocusPanel
}
/**
+ * Indicates that the security status is pending confirmation.
+ */
+ public void securityPending()
+ {
+ focusPeerPanel.securityPending();
+ }
+
+ /**
* Indicates that the security is timeouted, is not supported by the
* other end.
* @param evt Details about the event that caused this message.
@@ -646,4 +655,15 @@ public class ConferenceFocusPanel
}
}
}
+
+ /**
+ * Shows/hides the security panel.
+ *
+ * @param isVisible <tt>true</tt> to show the security panel, <tt>false</tt>
+ * to hide it
+ */
+ public void setSecurityPanelVisible(boolean isVisible)
+ {
+
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java
index 3e8adc1..d942385 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java
@@ -7,6 +7,7 @@
package net.java.sip.communicator.impl.gui.main.call.conference;
import java.awt.*;
+import java.awt.event.*;
import javax.swing.*;
@@ -15,6 +16,7 @@ import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.main.call.CallPeerAdapter; // disambiguation
import net.java.sip.communicator.impl.gui.main.presence.*;
import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.skin.*;
@@ -153,6 +155,8 @@ public class ConferencePeerPanel
this.callPeer = callPeer;
this.videoHandler = videoHandler;
+ this.securityPanel = SecurityPanel.create(this, callPeer, null);
+
this.setMute(callPeer.isMute());
this.setPeerImage(CallManager.getPeerImage(callPeer));
@@ -192,6 +196,23 @@ public class ConferencePeerPanel
securityOn(securityOnEvt);
}
+
+ securityStatusLabel.setBorder(
+ BorderFactory.createEmptyBorder(2, 5, 2, 5));
+
+ securityStatusLabel.setSecurityOff();
+
+ securityStatusLabel.addMouseListener(new MouseAdapter()
+ {
+ /**
+ * Invoked when a mouse button has been pressed on a component.
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ setSecurityPanelVisible(!callRenderer.getCallContainer()
+ .getCallWindow().getFrame().getGlassPane().isVisible());
+ }
+ });
}
/**
@@ -207,13 +228,33 @@ public class ConferencePeerPanel
{
super.securityOn(evt);
+ // If the securityOn is called without a specific event, we'll just call
+ // the super and we'll return.
+ if (evt == null)
+ return;
+
+ SrtpControl srtpControl = evt.getSecurityController();
+
+ // In case this is the local peer.
if (securityPanel == null)
+ return;
+
+ // if we have some other panel, using other control
+ if (securityPanel.getSecurityControl() == null
+ || !srtpControl.getClass().isInstance(
+ securityPanel.getSecurityControl()))
{
- securityPanel = SecurityPanel.create(evt.getSecurityController());
- securityPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0));
- this.addToCenter(securityPanel);
+ setSecurityPanelVisible(false);
+
+ securityPanel
+ = SecurityPanel.create(this, callPeer, srtpControl);
}
- securityPanel.refreshStates();
+
+ securityPanel.securityOn(evt);
+
+ if (srtpControl instanceof ZrtpControl
+ && !((ZrtpControl) srtpControl).isSecurityVerified())
+ setSecurityPanelVisible(true);
callPanel.refreshContainer();
}
@@ -227,16 +268,22 @@ public class ConferencePeerPanel
public void securityOff(CallPeerSecurityOffEvent evt)
{
super.securityOff(evt);
- if(securityPanel != null
- && !securityStatusLabel.isAudioSecurityOn()
- && !securityStatusLabel.isVideoSecurityOn())
+
+ if(securityPanel != null)
{
- securityPanel.getParent().remove(securityPanel);
- securityPanel = null;
+ securityPanel.securityOff(evt);
}
}
/**
+ * Indicates that the security status is pending confirmation.
+ */
+ public void securityPending()
+ {
+ super.securityPending();
+ }
+
+ /**
* Indicates that the security is timeouted, is not supported by the
* other end.
* @param evt Details about the event that caused this message.
@@ -306,7 +353,7 @@ public class ConferencePeerPanel
*
* @param state the state of the contained call peer
*/
- public void setPeerState(String state)
+ public void setPeerState(CallPeerState peerState, String state)
{
this.setParticipantState(state);
}
@@ -497,4 +544,146 @@ public class ConferencePeerPanel
{
return callPeer.getURI();
}
+
+ /**
+ * Shows/hides the security panel.
+ *
+ * @param isVisible <tt>true</tt> to show the security panel, <tt>false</tt>
+ * to hide it
+ */
+ public void setSecurityPanelVisible(boolean isVisible)
+ {
+ final JFrame callFrame = callRenderer.getCallContainer()
+ .getCallWindow().getFrame();
+
+ final JPanel glassPane = (JPanel) callFrame.getGlassPane();
+
+ if (!isVisible)
+ {
+ // Need to hide the security panel explicitly in order to keep the
+ // fade effect.
+ securityPanel.setVisible(false);
+ glassPane.setVisible(false);
+ glassPane.removeAll();
+ }
+ else
+ {
+ glassPane.setLayout(null);
+ glassPane.addMouseListener(new MouseListener()
+ {
+ public void mouseReleased(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mousePressed(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mouseExited(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mouseEntered(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+
+ public void mouseClicked(MouseEvent e)
+ {
+ redispatchMouseEvent(glassPane, e);
+ }
+ });
+
+ Point securityLabelPoint = securityStatusLabel.getLocation();
+
+ Point newPoint
+ = SwingUtilities.convertPoint(securityStatusLabel.getParent(),
+ securityLabelPoint.x, securityLabelPoint.y,
+ callFrame);
+
+ securityPanel.setBeginPoint(
+ new Point((int) newPoint.getX() + 15, 0));
+ securityPanel.setBounds(
+ 0, (int) newPoint.getY() - 5, callFrame.getWidth(), 110);
+
+ glassPane.add(securityPanel);
+ // Need to show the security panel explicitly in order to keep the
+ // fade effect.
+ securityPanel.setVisible(true);
+ glassPane.setVisible(true);
+
+ glassPane.addComponentListener(new ComponentAdapter()
+ {
+ /**
+ * Invoked when the component's size changes.
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ if (glassPane.isVisible())
+ {
+ glassPane.setVisible(false);
+ callFrame.removeComponentListener(this);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Re-dispatches glass pane mouse events only in case they occur on the
+ * security panel.
+ *
+ * @param glassPane the glass pane
+ * @param e the mouse event in question
+ */
+ private void redispatchMouseEvent(Component glassPane, MouseEvent e)
+ {
+ Point glassPanePoint = e.getPoint();
+
+ Point securityPanelPoint = SwingUtilities.convertPoint(
+ glassPane,
+ glassPanePoint,
+ securityPanel);
+
+ Component component;
+ Point componentPoint;
+
+ if (securityPanelPoint.y > 0)
+ {
+ component = securityPanel;
+ componentPoint = securityPanelPoint;
+ }
+ else
+ {
+ Container contentPane
+ = callRenderer.getCallContainer().getCallWindow()
+ .getFrame().getContentPane();
+
+ Point containerPoint = SwingUtilities.convertPoint(
+ glassPane,
+ glassPanePoint,
+ contentPane);
+
+ component = SwingUtilities.getDeepestComponentAt(contentPane,
+ containerPoint.x, containerPoint.y);
+
+ componentPoint = SwingUtilities.convertPoint(contentPane,
+ glassPanePoint, component);
+ }
+
+ if (component != null)
+ component.dispatchEvent(new MouseEvent( component,
+ e.getID(),
+ e.getWhen(),
+ e.getModifiers(),
+ componentPoint.x,
+ componentPoint.y,
+ e.getClickCount(),
+ e.isPopupTrigger()));
+
+ e.consume();
+ }
}
diff --git a/src/net/java/sip/communicator/util/swing/FadeInBalloonPanel.java b/src/net/java/sip/communicator/util/swing/FadeInBalloonPanel.java
new file mode 100644
index 0000000..2d62c56
--- /dev/null
+++ b/src/net/java/sip/communicator/util/swing/FadeInBalloonPanel.java
@@ -0,0 +1,190 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.util.swing;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+import javax.swing.*;
+
+import org.jvnet.lafwidget.animation.*;
+
+/**
+ * The <tt>FadeInBaloonPanel</tt> is a semi-transparent "balloon" panel, which
+ * could be shown in a glass pane for example. You can define a begin point,
+ * where the balloon triangle would show.
+ *
+ * @author Yana Stamcheva
+ */
+public class FadeInBalloonPanel
+ extends TransparentPanel
+{
+ /**
+ * The begin point, where the balloon triangle will be shown.
+ */
+ private Point beginPoint;
+
+ /**
+ * The begin point shift, which defines the rectangle point shift.
+ */
+ private final static int beginPointShift = 6;
+
+ /**
+ * Sets the begin point.
+ *
+ * @param beginPoint the begin point
+ */
+ public void setBeginPoint(Point beginPoint)
+ {
+ this.beginPoint = beginPoint;
+ }
+
+ /**
+ * Overrides the <code>paintComponent</code> method of <tt>JButton</tt> to
+ * paint the button background and icon, and all additional effects of this
+ * configurable button.
+ *
+ * @param g The Graphics object.
+ */
+ protected void paintComponent(Graphics g)
+ {
+ g = g.create();
+ try
+ {
+ internalPaintComponent((Graphics2D) g);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+
+ /**
+ * Paints this button.
+ * @param g the <tt>Graphics</tt> object used for painting
+ */
+ private void internalPaintComponent(Graphics2D g)
+ {
+ AntialiasingManager.activateAntialiasing(g);
+ /*
+ * As JComponent#paintComponent says, if you do not invoke super's
+ * implementation you must honor the opaque property, that is if this
+ * component is opaque, you must completely fill in the background in a
+ * non-opaque color. If you do not honor the opaque property you will
+ * likely see visual artifacts.
+ */
+ if (isOpaque())
+ {
+ g.setColor(getBackground());
+ g.fillRect(0, 0, getWidth(), getHeight());
+ }
+
+ // Paint a roll over fade out.
+ FadeTracker fadeTracker = FadeTracker.getInstance();
+
+ float visibility = isVisible() ? 0.8f : 0.0f;
+ if (fadeTracker.isTracked(this, FadeKind.ROLLOVER))
+ {
+ visibility = fadeTracker.getFade(this, FadeKind.ROLLOVER);
+ }
+
+ g.setColor(new Color(0f, 0f, 0f, visibility));
+
+ int y = 0;
+
+ // draw triangle (polygon)
+ if (beginPoint != null)
+ {
+ y = beginPointShift;
+
+ int x1Points[] = { beginPoint.x,
+ beginPoint.x + beginPointShift,
+ beginPoint.x - beginPointShift};
+
+ int y1Points[] = { beginPoint.y,
+ beginPoint.y + beginPointShift,
+ beginPoint.y + beginPointShift};
+
+ GeneralPath polygon =
+ new GeneralPath(GeneralPath.WIND_EVEN_ODD,
+ x1Points.length);
+
+ polygon.moveTo(x1Points[0], y1Points[0]);
+
+ for (int index = 1; index < x1Points.length; index++) {
+ polygon.lineTo(x1Points[index], y1Points[index]);
+ };
+
+ polygon.closePath();
+ g.fill(polygon);
+ }
+
+ if (visibility != 0.0f)
+ {
+ g.fillRoundRect(
+ 0, y, this.getWidth(), this.getHeight(), 10, 10);
+ }
+ }
+
+ /**
+ * The <tt>ButtonRepaintCallback</tt> is charged to repaint this button
+ * when the fade animation is performed.
+ */
+ private class PanelRepaintCallback implements FadeTrackerCallback
+ {
+ public void fadeEnded(FadeKind arg0)
+ {
+ repaintLater();
+ }
+
+ public void fadePerformed(FadeKind arg0, float arg1)
+ {
+ repaintLater();
+ }
+
+ private void repaintLater()
+ {
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ FadeInBalloonPanel.this.repaint();
+ }
+ });
+ }
+
+ public void fadeReversed(FadeKind arg0, boolean arg1, float arg2)
+ {
+ }
+ }
+
+ /**
+ * Shows/hides this panel.
+ *
+ * @param isVisible <tt>true</tt> to show this panel, <tt>false</tt> to
+ * hide it
+ */
+ public void setVisible(boolean isVisible)
+ {
+ FadeTracker fadeTracker = FadeTracker.getInstance();
+
+ if (isVisible)
+ {
+ fadeTracker.trackFadeIn(FadeKind.ROLLOVER,
+ FadeInBalloonPanel.this,
+ true,
+ new PanelRepaintCallback());
+ }
+ else
+ {
+ fadeTracker.trackFadeOut(FadeKind.ROLLOVER,
+ FadeInBalloonPanel.this,
+ true,
+ new PanelRepaintCallback());
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java b/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java
index fc5030c..e9d6775 100644
--- a/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java
+++ b/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java
@@ -300,7 +300,7 @@ public class SIPCommTextFieldUI
}
JTextComponent c = getComponent();
-
+
if(c == null)
return null;