1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.exchange.auth;
21
22 import davmail.BundleMessage;
23 import davmail.Settings;
24 import davmail.ui.tray.SwtGatewayTray;
25 import org.apache.log4j.Logger;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.browser.Browser;
28 import org.eclipse.swt.browser.LocationEvent;
29 import org.eclipse.swt.browser.LocationListener;
30 import org.eclipse.swt.layout.FillLayout;
31 import org.eclipse.swt.widgets.Display;
32 import org.eclipse.swt.widgets.Shell;
33
34 import java.util.concurrent.TimeUnit;
35 import java.util.concurrent.locks.Condition;
36 import java.util.concurrent.locks.ReentrantLock;
37
38
39
40
41 public class O365InteractiveAuthenticatorSWT {
42
43 private static final Logger LOGGER = Logger.getLogger(O365InteractiveAuthenticatorSWT.class);
44
45 private O365InteractiveAuthenticator authenticator;
46
47 Shell shell;
48 Browser browser;
49 private final ReentrantLock lock = new ReentrantLock();
50 private final Condition ready = lock.newCondition();
51 private boolean isReady = false;
52 private Error error;
53
54 public O365InteractiveAuthenticatorSWT() {
55
56 }
57
58 public void setO365InteractiveAuthenticator(O365InteractiveAuthenticator authenticator) {
59 this.authenticator = authenticator;
60 }
61
62 public void authenticate(final String initUrl, final String redirectUri) {
63
64 SwtGatewayTray.initDisplay();
65
66
67 System.setProperty("org.eclipse.swt.browser.Edge.allowSingleSignOnUsingOSPrimaryAccount",
68 Settings.getProperty("davmail.oauth.allowSingleSignOnUsingOSPrimaryAccount", "true"));
69
70 Display.getDefault().asyncExec(() -> {
71 try {
72 shell = new Shell(Display.getDefault());
73 shell.setText(BundleMessage.format("UI_DAVMAIL_GATEWAY"));
74 shell.setSize(600, 600);
75
76 shell.setLayout(new FillLayout());
77
78 shell.setImage(SwtGatewayTray.loadSwtImage("tray.png", 32));
79
80 shell.addListener(SWT.Close, event -> {
81 if (!authenticator.isAuthenticated && authenticator.errorCode == null) {
82 authenticator.errorCode = "user closed authentication window";
83 }
84 dispose();
85 });
86
87 browser = new Browser(shell, SWT.NONE);
88
89 browser.setUrl(initUrl);
90 browser.addTitleListener(titleEvent -> shell.setText("DavMail: " + titleEvent.title));
91 browser.addLocationListener(new LocationListener() {
92 @Override
93 public void changing(LocationEvent locationEvent) {
94 LOGGER.debug("Navigate to " + locationEvent.toString());
95 String location = locationEvent.location;
96
97 if (location.startsWith(redirectUri)) {
98
99 LOGGER.debug("Location starts with redirectUri, check code");
100 authenticator.handleCode(location);
101
102 shell.close();
103 dispose();
104 }
105
106 }
107
108 @Override
109 public void changed(LocationEvent locationEvent) {
110 LOGGER.debug("Page changed: " + locationEvent.toString());
111 }
112 });
113
114 lock.lock();
115 try {
116 isReady = true;
117 ready.signalAll();
118 } finally {
119 lock.unlock();
120 }
121
122 shell.open();
123 shell.setActive();
124 } catch (Throwable e) {
125 LOGGER.error("Error in SWT thread", e);
126 lock.lock();
127 try {
128 error = new Error(e);
129 ready.signalAll();
130 } finally {
131 lock.unlock();
132 }
133 }
134
135 });
136
137 lock.lock();
138 try {
139 while (!isReady) {
140 ready.await();
141 if (error != null) {
142 throw error;
143 }
144 }
145 } catch (InterruptedException e) {
146 Thread.currentThread().interrupt();
147 } finally {
148 lock.unlock();
149 }
150 }
151
152 protected void dispose() {
153 Display.getDefault().asyncExec(() -> {
154 if (browser != null) {
155 browser.dispose();
156 }
157 if (shell != null) {
158 shell.dispose();
159 }
160 });
161 }
162 }